Adding notifications
This commit is contained in:
parent
0f0ef9c08b
commit
6906455981
3 changed files with 79 additions and 4 deletions
63
app.py
63
app.py
|
|
@ -3,7 +3,7 @@ from flask import (
|
||||||
send_from_directory, session, url_for)
|
send_from_directory, session, url_for)
|
||||||
import hashlib
|
import hashlib
|
||||||
from peewee import *
|
from peewee import *
|
||||||
import datetime, time, re, os, string
|
import datetime, time, re, os, sys, string, json
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
DATABASE = 'coriplus.sqlite'
|
DATABASE = 'coriplus.sqlite'
|
||||||
|
|
@ -59,6 +59,13 @@ class User(BaseModel):
|
||||||
(Relationship.to_user == user))
|
(Relationship.to_user == user))
|
||||||
.exists())
|
.exists())
|
||||||
|
|
||||||
|
def unseen_notification_count(self):
|
||||||
|
return len(Notification
|
||||||
|
.select()
|
||||||
|
.where(
|
||||||
|
Notification.target == self
|
||||||
|
))
|
||||||
|
|
||||||
# A single public message.
|
# A single public message.
|
||||||
class Message(BaseModel):
|
class Message(BaseModel):
|
||||||
# The type of the message.
|
# The type of the message.
|
||||||
|
|
@ -98,9 +105,16 @@ class Upload(BaseModel):
|
||||||
def filename(self):
|
def filename(self):
|
||||||
return str(self.id) + '.' + self.type
|
return str(self.id) + '.' + self.type
|
||||||
|
|
||||||
|
class Notification(BaseModel):
|
||||||
|
type = TextField()
|
||||||
|
target = ForeignKeyField(User, backref='notifications')
|
||||||
|
detail = TextField()
|
||||||
|
pub_date = DateTimeField()
|
||||||
|
seen = IntegerField(default=0)
|
||||||
|
|
||||||
def create_tables():
|
def create_tables():
|
||||||
with database:
|
with database:
|
||||||
database.create_tables([User, Message, Relationship, Upload])
|
database.create_tables([User, Message, Relationship, Upload, Notification])
|
||||||
if not os.path.isdir(UPLOAD_DIRECTORY):
|
if not os.path.isdir(UPLOAD_DIRECTORY):
|
||||||
os.makedirs(UPLOAD_DIRECTORY)
|
os.makedirs(UPLOAD_DIRECTORY)
|
||||||
|
|
||||||
|
|
@ -193,6 +207,33 @@ def login_required(f):
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
|
def push_notification(type, target, **kwargs):
|
||||||
|
try:
|
||||||
|
if isinstance(target, str):
|
||||||
|
target = User.get(User.username == target)
|
||||||
|
Notification.create(
|
||||||
|
type=type,
|
||||||
|
target=target,
|
||||||
|
detail=json.dumps(kwargs),
|
||||||
|
pub_date=datetime.datetime.now()
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
sys.excepthook(*sys.exc_info())
|
||||||
|
|
||||||
|
def unpush_notification(type, target, **kwargs):
|
||||||
|
try:
|
||||||
|
if isinstance(target, str):
|
||||||
|
target = User.get(User.username == target)
|
||||||
|
(Notification
|
||||||
|
.delete()
|
||||||
|
.where(
|
||||||
|
(Notification.type == type) &
|
||||||
|
(Notification.target == target) &
|
||||||
|
(Notification.detail == json.dumps(kwargs))
|
||||||
|
))
|
||||||
|
except Exception:
|
||||||
|
sys.excepthook(*sys.exc_info())
|
||||||
|
|
||||||
# given a template and a SelectQuery instance, render a paginated list of
|
# given a template and a SelectQuery instance, render a paginated list of
|
||||||
# objects from the query inside the template
|
# objects from the query inside the template
|
||||||
def object_list(template_name, qr, var_name='object_list', **kwargs):
|
def object_list(template_name, qr, var_name='object_list', **kwargs):
|
||||||
|
|
@ -305,30 +346,34 @@ def user_detail(username):
|
||||||
@app.route('/+<username>/follow/', methods=['POST'])
|
@app.route('/+<username>/follow/', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def user_follow(username):
|
def user_follow(username):
|
||||||
|
cur_user = get_current_user()
|
||||||
user = get_object_or_404(User, User.username == username)
|
user = get_object_or_404(User, User.username == username)
|
||||||
try:
|
try:
|
||||||
with database.atomic():
|
with database.atomic():
|
||||||
Relationship.create(
|
Relationship.create(
|
||||||
from_user=get_current_user(),
|
from_user=cur_user,
|
||||||
to_user=user,
|
to_user=user,
|
||||||
created_date=datetime.datetime.now())
|
created_date=datetime.datetime.now())
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
flash('You are following %s' % user.username)
|
flash('You are following %s' % user.username)
|
||||||
|
push_notification('follow', user, user=cur_user.id)
|
||||||
return redirect(url_for('user_detail', username=user.username))
|
return redirect(url_for('user_detail', username=user.username))
|
||||||
|
|
||||||
@app.route('/+<username>/unfollow/', methods=['POST'])
|
@app.route('/+<username>/unfollow/', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def user_unfollow(username):
|
def user_unfollow(username):
|
||||||
|
cur_user = get_current_user()
|
||||||
user = get_object_or_404(User, User.username == username)
|
user = get_object_or_404(User, User.username == username)
|
||||||
(Relationship
|
(Relationship
|
||||||
.delete()
|
.delete()
|
||||||
.where(
|
.where(
|
||||||
(Relationship.from_user == get_current_user()) &
|
(Relationship.from_user == cur_user) &
|
||||||
(Relationship.to_user == user))
|
(Relationship.to_user == user))
|
||||||
.execute())
|
.execute())
|
||||||
flash('You are no longer following %s' % user.username)
|
flash('You are no longer following %s' % user.username)
|
||||||
|
unpush_notification('follow', user, user=cur_user.id)
|
||||||
return redirect(url_for('user_detail', username=user.username))
|
return redirect(url_for('user_detail', username=user.username))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -356,6 +401,16 @@ def create():
|
||||||
|
|
||||||
return render_template('create.html')
|
return render_template('create.html')
|
||||||
|
|
||||||
|
@app.route('/notifications/')
|
||||||
|
@login_required
|
||||||
|
def notifications():
|
||||||
|
user = get_current_user()
|
||||||
|
notifications = (Notification
|
||||||
|
.select()
|
||||||
|
.where(Notification.target == user)
|
||||||
|
.order_by(Notification.pub_date.desc()))
|
||||||
|
return object_list('notifications.html', notifications, 'notification_list', json=json, User=User)
|
||||||
|
|
||||||
@app.route('/uploads/<id>.jpg')
|
@app.route('/uploads/<id>.jpg')
|
||||||
def uploads(id, type='jpg'):
|
def uploads(id, type='jpg'):
|
||||||
return send_from_directory(UPLOAD_DIRECTORY, id + '.' + type)
|
return send_from_directory(UPLOAD_DIRECTORY, id + '.' + type)
|
||||||
|
|
|
||||||
10
templates/includes/notification.html
Normal file
10
templates/includes/notification.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{% set detail = json.loads(notification.detail) %}
|
||||||
|
|
||||||
|
{% if notification.type == 'follow' %}
|
||||||
|
{% set user = User[detail['user']] %}
|
||||||
|
<p><a href="/+{{ user.username }}">{{ user.username }}</a> started following you.</p>
|
||||||
|
{% else %}
|
||||||
|
<p>Unknown Notification</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<small>{{ notification.pub_date | human_date }}</small>
|
||||||
10
templates/notifications.html
Normal file
10
templates/notifications.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<h2>Notifications</h2>
|
||||||
|
<ul>
|
||||||
|
{% for notification in notification_list %}
|
||||||
|
<li>{% include "includes/notification.html" %}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% include "includes/pagination.html" %}
|
||||||
|
{% endblock %}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue