Compare commits

...

2 Commits

Author SHA1 Message Date
7dd1c9bf30 subscription system backend added 2018-10-12 10:35:10 -04:00
20f47f02a8 profile link in header bar 2018-10-12 08:07:48 -04:00
14 changed files with 96 additions and 68 deletions

View File

@ -5,7 +5,7 @@ By popular demand, I'm building a better anonkun. It doesn't do much right now t
Python 3.6+
PostgreSQL 10.4+
Redis 4.0.10+
Python packages: `django psycopg2 channels channels_redis jinja2 argon2-cffi bleach requests python-magic django-taggit`
Python packages: `django psycopg2 channels channels_redis jinja2 argon2-cffi bleach requests python-magic django-taggit django-user-messages`
## Install
```

View File

@ -23,8 +23,10 @@
<span><a onclick="toggle_header();" href="javascript:void(0);"></a></span>
</div>
<ul id="alerts">
{% for message in get_messages(request) %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% for message in get_messages(request=request) %}
{% if "subscription" not in message.tags %}
<li class="{{ message.tags }}">{{ message }}</li>
{% endif %}
{% endfor %}
</ul>
<div id="content">{% block content %}{% endblock %}</div>

View File

@ -86,7 +86,7 @@ def message(socket, data):
m = Message(
quest=quest,
message=message)
if user.username:
if user.is_authenticated:
m.user = user
m.save()
@ -551,7 +551,7 @@ def vote(socket, data):
option=option,
ip_address=ip_address
)
if user.username:
if user.is_authenticated:
pv.user = user
pv.save()

View File

@ -18,32 +18,7 @@
<script>window.onload = load;</script>
{% endblock %}
{% block header %}
{% if request.user == quest.owner %}
<span><a href="{{ url('quest:edit_quest', args=[quest_id, page_num]) }}">Edit Quest</a></span>
{% endif %}
<span id="pageSelection">
<select onChange="window.location.href=this.value">
<optgroup label="Pages">
{% for page in pages %}
<option value="{{ url('quest:quest', args=[quest_id, page.page_num]) }}"{% if page.page_num == page_num %} selected="yes" {% if vars.update({'next_page': loop.nextitem}) %}{% endif %}{% endif %}>{{ page.title }}</option>
{% endfor %}
</optgroup>
{% if appendices %}
<optgroup label="Appendices">
{% for appendix in appendices %}
<option value="{{ url('quest:quest', args=[quest_id, appendix.page_num]) }}"{% if appendix.page_num == page_num %} selected="yes"{% endif %}>{{ appendix.title }}</option>
{% endfor %}
</optgroup>
{% endif %}
</select>
</span>
<span id="live" style="display:{% if quest.live %}initial{% else %}none{% endif %};">
LIVE
</span>
<span id="liveIn" style="display:{% if quest.live_time and not quest.live %}initial{% else %}none{% endif %};">
Live in: <span id="liveCountdown"></span> (<span id="liveTime">{% if quest.live_time %}{{ localtime(quest.live_time).strftime('%Y-%m-%d %H:%M') }}{% endif %}</span>)
</span>
<span id="toggleChat"><a onclick="toggle_chat()" href="javascript:void(0);">{% if request.session.get("hide_chat") == True %}←{% else %}→{% endif %}</a></span>
{% include "quest/quest_header.html" %}
{% endblock %}
{% block content %}
<div id="questPane" style="width:{% if request.session.get("hide_chat") == True %}100%{% else %}70%{% endif %};">

View File

@ -0,0 +1,31 @@
{% if request.user == quest.owner %}
<span><a href="{{ url('quest:edit_quest', args=[quest_id, page_num]) }}">Edit Quest</a></span>
{% endif %}
<span id="pageSelection">
<select onChange="window.location.href=this.value">
<optgroup label="Pages">
{% for page in pages %}
<option value="{{ url('quest:quest', args=[quest_id, page.page_num]) }}"{% if page.page_num == page_num %} selected="yes" {% if vars.update({'next_page': loop.nextitem}) %}{% endif %}{% endif %}>{{ page.title }}</option>
{% endfor %}
</optgroup>
{% if appendices %}
<optgroup label="Appendices">
{% for appendix in appendices %}
<option value="{{ url('quest:quest', args=[quest_id, appendix.page_num]) }}"{% if appendix.page_num == page_num %} selected="yes"{% endif %}>{{ appendix.title }}</option>
{% endfor %}
</optgroup>
{% endif %}
</select>
</span>
<span id="live" style="display:{% if quest.live %}initial{% else %}none{% endif %};">
LIVE
</span>
<span id="liveIn" style="display:{% if quest.live_time and not quest.live %}initial{% else %}none{% endif %};">
Live in: <span id="liveCountdown"></span> (<span id="liveTime">{% if quest.live_time %}{{ localtime(quest.live_time).strftime('%Y-%m-%d %H:%M') }}{% endif %}</span>)
</span>
<span id="space"></span>
{% if request.user.is_authenticated %}
<span id="profileLink"><a href="{{ url('user:profile', args=[request.user.id]) }}">{{ request.user.username }}</a></span>
{% endif %}
<span id="toggleChat"><a onclick="toggle_chat()" href="javascript:void(0);">{% if request.session.get("hide_chat") == True %}←{% else %}→{% endif %}</a></span>

View File

@ -20,37 +20,7 @@
<script>window.onload = load;</script>
{% endblock %}
{% block header %}
{% if request.user == quest.owner %}
<span><a href="{{ url('quest:edit_quest', args=[quest_id, page_num]) }}">Edit Quest</a></span>
{% endif %}
<span>
<select onChange="window.location.href=this.value">
<optgroup label="Pages">
{% for page in pages %}
<option value="{{ url('quest:quest', args=[quest_id, page.page_num]) }}"{% if page.page_num == page_num %} selected="yes" {% if vars.update({'next_page': loop.nextitem }) %}{% endif %}{% endif %}>{{ page.title }}</option>
{% endfor %}
</optgroup>
{% if appendices %}
<optgroup label="Appendices">
{% for appendix in appendices %}
<option value="{{ url('quest:quest', args=[quest_id, appendix.page_num]) }}"{% if appendix.page_num == page_num %} selected="yes"{% endif %}>{{ appendix.title }}</option>
{% endfor %}
</optgroup>
{% endif %}
</select>
</span>
{% if quest.live %}
<span id="live">
LIVE
</span>
{% else %}
{% if quest.live_time %}
<span id="liveIn">
Live in: <span id="liveCountdown"></span> (<span id="liveTime">{{ localtime(quest.live_time).strftime('%Y-%m-%d %H:%M') }}</span>)
</span>
{% endif %}
{% endif %}
<span id="toggleChat"><a onclick="toggle_chat()" href="javascript:void(0);">{% if request.session.get("hide_chat") == True %}←{% else %}→{% endif %}</a></span>
{% include "quest/quest_header.html" %}
{% endblock %}
{% block content %}
<div id="questPane" style="width:{% if request.session.get("hide_chat") == True %}100%{% else %}70%{% endif %};">
@ -67,6 +37,12 @@
<input type="submit">
</form>
{% endif %}
{% if request.user.is_authenticated %}
<form id="subscribe" method="post" action="{{ url('quest:subscribe', kwargs={'quest_id': quest_id}) }}">
{{ csrf_input }}
<a onclick="document.getElementById('subscribe').submit()">Subscribe</a>
</form>
{% endif %}
<h3>Pages</h3>
<ul>
{% for page in pages %}

View File

@ -14,8 +14,8 @@ h3 {
padding: 0.25em;
}
#toggleChat {
margin-left: auto;
#space {
margin-right: auto;
}
#questPane {

View File

@ -10,6 +10,7 @@ app_name = 'quest'
urlpatterns = [
path('', views.index, name='index'),
path('<int:quest_id>/new_tag', views.new_tag, name='new_tag'),
path('<int:quest_id>/subscribe', views.subscribe, name='subscribe'),
path('<int:quest_id>/edit_quest', views.edit_quest, name='edit_quest'),
path('<int:quest_id>/<page_num>/edit_quest', views.edit_quest, name='edit_quest'),
path('<int:quest_id>', views.quest, name='quest'),

View File

@ -5,6 +5,7 @@ Quest and quest accessory views.
from datetime import timedelta, datetime, timezone
import bleach
from user_messages import api
from django.views.decorators.http import require_POST
from django.contrib import messages
from django.shortcuts import render, redirect
@ -85,6 +86,7 @@ def edit_quest(request, quest_id, page_num='0'):
Edit quest page. Only available to the QM.
"""
quest = Quest.objects.get(id=quest_id)
prev_live = quest.live
if quest.owner != request.user:
return redirect('quest:quest', quest_id=quest_id, page_num=page_num)
if request.method == 'POST':
@ -119,6 +121,15 @@ def edit_quest(request, quest_id, page_num='0'):
if data['live_time']:
data['live_time'] =data['live_time'].strftime('%Y-%m-%d %H:%M')
send_to_websocket('live', quest_id, data)
if prev_live == False and quest.live == True:
subscribers = quest.user_set.all()
for subscriber in subscribers:
api.info(
subscriber,
f"{quest.title} has gone live!",
extra_tags='subscription',
deliver_once=False
)
return redirect('quest:quest',quest_id=quest.id, page_num=page_num)
else:
messages.error(request, "Error")
@ -176,3 +187,13 @@ def new_tag(request, quest_id):
quest.tags.add(tag)
return redirect('quest:quest', quest_id=quest_id, page_num='0')
@require_POST
def subscribe(request, quest_id):
"""Endpoint for users to subscribe to a quest."""
if not request.user.is_authenticated:
return redirect('login:index')
request.user.subscriptions.add(Quest.objects.get(id=quest_id))
messages.success(request, "Subscribed")
return redirect('quest:quest', quest_id=quest_id, page_num='0')

View File

@ -3,8 +3,8 @@
Custom Jinja2 environment.
"""
import jinja2
from user_messages import api
from django.urls import reverse
from django.contrib import messages
from django.utils.timezone import template_localtime
from django.contrib.staticfiles.storage import staticfiles_storage
@ -21,7 +21,7 @@ def environment(**options):
'url': reverse,
'static': staticfiles_storage.url,
'get_messages': messages.get_messages,
'get_messages': api.get_messages,
'localtime': template_localtime,
})
return env

View File

@ -34,6 +34,7 @@ INSTALLED_APPS = [
'django.contrib.postgres',
'channels',
'taggit',
'user_messages',
'user.apps.UserConfig',
'homepage.apps.HomepageConfig',
'quest.apps.QuestConfig',
@ -73,7 +74,8 @@ TEMPLATES = [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
#'django.contrib.messages.context_processors.messages',
'user_messages.context_processors.messages',
],
},
},

1
todo
View File

@ -4,7 +4,6 @@ Front page to show new quests
Webm posting
(you) counter
Account managament
Display profile link in header bar
Quote backlinks
Email
RSS

View File

@ -0,0 +1,19 @@
# Generated by Django 2.1.1 on 2018-10-12 13:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('quest', '0010_quest_banner_url'),
('user', '0002_user_anonymize'),
]
operations = [
migrations.AddField(
model_name='user',
name='subscriptions',
field=models.ManyToManyField(to='quest.Quest'),
),
]

View File

@ -9,6 +9,7 @@ from django.contrib.auth.models import AbstractUser
from django.core.validators import MinLengthValidator, MaxLengthValidator
from .validators import CharValidator
from quest.models import Quest
class User(AbstractUser):
"""
@ -45,6 +46,7 @@ class User(AbstractUser):
help_text="Let's be honest, your name doesn't add anything to " \
+ "the conversation."
)
subscriptions = models.ManyToManyField(Quest)
def get_full_name(self):
return None