mirror of https://git.skyjake.fi/gemini/bubble.git
User flairs and locking comments
This commit is contained in:
parent
69823b3f28
commit
17b7d6eaa5
19
50_bubble.py
19
50_bubble.py
|
@ -178,10 +178,22 @@ Bubble is open source:
|
|||
return False
|
||||
return self.is_deletable(post)
|
||||
|
||||
def is_lockable(self, post: Post):
|
||||
return self.is_deletable(post)
|
||||
|
||||
def is_title_editable(self, post: Post):
|
||||
# Moderators can edit post titles.
|
||||
return self.is_deletable(post)
|
||||
|
||||
def is_commenting_enabled(self, post: Post):
|
||||
if not post:
|
||||
return False
|
||||
if self.user.role == User.ADMIN:
|
||||
return True
|
||||
if post.flags & Post.LOCKED_FLAG:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_antenna_enabled(self):
|
||||
if self.user:
|
||||
return self.user.role != User.LIMITED
|
||||
|
@ -259,6 +271,7 @@ Bubble is open source:
|
|||
else:
|
||||
age = post.age(tz=self.tz)
|
||||
bell = ' 🔔' if post.num_notifs else ''
|
||||
flair = f' [{post.poster_flair}]' if post.poster_flair else ''
|
||||
|
||||
SHORT_PREVIEW_LEN = 160
|
||||
|
||||
|
@ -301,6 +314,8 @@ Bubble is open source:
|
|||
else:
|
||||
post_icon = post.poster_avatar
|
||||
post_label = post.poster_name
|
||||
if not (is_user_post and context and context.id == post.subspace):
|
||||
post_label += flair
|
||||
post_path = f'/u/{post.poster_name}'
|
||||
meta_icon = '💬'
|
||||
|
||||
|
@ -316,7 +331,7 @@ Bubble is open source:
|
|||
# Activity feeds use ts_comment timestamps, so the post author's name is at the top
|
||||
# because the meta line is associated with the latest comment instead.
|
||||
if is_activity_feed and sub:
|
||||
post_label += f' · {post.poster_avatar} {post.poster_name}'
|
||||
post_label += f' · {post.poster_avatar} {post.poster_name}{flair}'
|
||||
|
||||
src = f'=> {post_path} {post_icon} {post_label}{rotation}\n'
|
||||
|
||||
|
@ -861,7 +876,7 @@ Deleting a subspace will delete all posts and comments in the subspace, i.e., th
|
|||
elif req.path.startswith(self.path + 'comment/'):
|
||||
return make_comment(session)
|
||||
|
||||
elif re.match(r'^(like|unlike|vote|follow|unfollow|mute|unmute|notif|thanks|react|unreact|report|remind|transmit)/.*',
|
||||
elif re.match(r'^(like|unlike|vote|follow|unfollow|mute|unmute|lock|unlock|notif|thanks|react|unreact|report|remind|transmit)/.*',
|
||||
req.path[len(self.path):]):
|
||||
return user_actions(session)
|
||||
|
||||
|
|
18
admin.py
18
admin.py
|
@ -60,6 +60,7 @@ def admin_actions(session):
|
|||
|
||||
page += "## Users\n\n"
|
||||
page += f'=> review-users/ ✔️ Review limited users\n'
|
||||
page += f'=> flair/{token} 📛 Set user flair\n'
|
||||
page += f'=> create-user/{token} 👤 Create new user\n'
|
||||
page += f'=> password/{token} 🔑 Generate a random password for user\n'
|
||||
page += f'=> revoke/{token} 🛂 Revoke certificates of user\n'
|
||||
|
@ -79,7 +80,7 @@ def admin_actions(session):
|
|||
|
||||
return page
|
||||
|
||||
found = re.search(r'^admin/(create-user|password|revoke|delete-user|omit-subspace|include-subspace|delete-subspace)/([0-9a-zA-Z]{10})$',
|
||||
found = re.search(r'^admin/(create-user|password|revoke|flair|delete-user|omit-subspace|include-subspace|delete-subspace)/([0-9a-zA-Z]{10})$',
|
||||
req.path[len(session.path):])
|
||||
if not found:
|
||||
return 59, "Bad request"
|
||||
|
@ -152,6 +153,21 @@ def admin_actions(session):
|
|||
db.remove_certificate(user, None)
|
||||
page += f'Certificates of user "{name}" (ID: {user.id}) have been unregistered.\n'
|
||||
|
||||
elif action == 'flair':
|
||||
try:
|
||||
parts = clean_query(req).split()
|
||||
name = parts[0]
|
||||
if not is_valid_name(name):
|
||||
return 10, 'Enter user name followed by flair (e.g., "john Friendly"):'
|
||||
except:
|
||||
return 10, 'Enter user name followed by flair (e.g., "john Friendly"):'
|
||||
flair = clean_query(req)[len(name):].strip()
|
||||
user = db.get_user(name=name)
|
||||
if not user:
|
||||
return 51, 'Not found'
|
||||
db.update_user(user, flair=flair)
|
||||
page += f'Flair of user "{name}" (ID: {user.id}) has been set to: [{flair}]\n'
|
||||
|
||||
elif action == 'delete-user':
|
||||
if not is_valid_name(name):
|
||||
return 10, "Enter user to delete: (NOTE: All of their posts and comments will be deleted.)"
|
||||
|
|
|
@ -283,7 +283,7 @@ def make_composer_page(session):
|
|||
return 30, link
|
||||
|
||||
if post_action == 'featured-link':
|
||||
db.update_post(post, flags=post.flags ^ Post.DISABLE_FEATURED_LINK)
|
||||
db.update_post(post, flags=post.flags ^ Post.DISABLE_FEATURED_LINK_FLAG)
|
||||
db.update_post_summary(post)
|
||||
return 30, link
|
||||
|
||||
|
@ -389,7 +389,7 @@ def make_composer_page(session):
|
|||
if not subspace.flags & Subspace.OMIT_FROM_ALL_FLAG:
|
||||
page += f'=> {link}/omit-all {CHECKS[nonzero(post.flags & Post.OMIT_FROM_ALL_FLAG)]} Omit {post_type.lower()} from All Posts\n'
|
||||
page += f'=> {link}/omit-feed {CHECKS[nonzero(post.flags & Post.OMIT_FROM_FEED_FLAG)]} Omit {post_type.lower()} from Gemini/Atom feed\n'
|
||||
page += f'=> {link}/featured-link {CHECKS[is_zero(post.flags & Post.DISABLE_FEATURED_LINK)]} Feature first link\n'
|
||||
page += f'=> {link}/featured-link {CHECKS[is_zero(post.flags & Post.DISABLE_FEATURED_LINK_FLAG)]} Feature first link\n'
|
||||
else:
|
||||
page += f"=> /{subspace.title()} Limited account: post is visible only in {subspace.title()}\n"
|
||||
if is_issue_tracker:
|
||||
|
@ -489,12 +489,14 @@ def make_comment(session):
|
|||
post = db.get_post(post_id)
|
||||
if not post:
|
||||
return 51, 'Not found'
|
||||
if post.flags & Post.LOCKED_FLAG and session.user.role != User.ADMIN:
|
||||
return 61, 'Post is locked'
|
||||
|
||||
special = None
|
||||
if session.is_gemini:
|
||||
com_text = clean_query(req)
|
||||
if len(com_text) == 0:
|
||||
return 10, 'New comment: (draft by ending with a backslash; see Help for special commands)'
|
||||
return 10, 'New comment: (draft a long comment by ending with a backslash)'
|
||||
|
||||
if com_text == '.':
|
||||
special = 'draft'
|
||||
|
|
|
@ -30,3 +30,6 @@ UPDATE users SET notif=notif|0x040000;
|
|||
|
||||
-- Migration from v6 to v7 --
|
||||
UPDATE users SET notif=notif|0x100000;
|
||||
|
||||
-- Migration from v7 to v8 --
|
||||
ALTER TABLE users ADD COLUMN flair VARCHAR(30) DEFAULT '';
|
32
feeds.py
32
feeds.py
|
@ -190,7 +190,7 @@ def make_post_page_or_configure_feed(session):
|
|||
# If there are plain URIs in the content, make segments for them.
|
||||
nonlinks = parse_nonlink_uris(body)
|
||||
if nonlinks:
|
||||
db.update_post(post, flags=post.flags | Post.DISABLE_FEATURED_LINK)
|
||||
db.update_post(post, flags=post.flags | Post.DISABLE_FEATURED_LINK_FLAG)
|
||||
for uri in nonlinks:
|
||||
db.create_segment(post, Segment.LINK, url=uri, content='')
|
||||
db.update_post_summary(post)
|
||||
|
@ -248,6 +248,11 @@ def make_post_page_or_configure_feed(session):
|
|||
if not session.is_context_tracker and (session.user.id == post.user or session.is_user_mod):
|
||||
actions.append(f'=> /edit-tags/{post.id} 🏷️ Add/remove tags\n')
|
||||
actions.append(f'=> /remind/{post.id} 🔔 Remind me\n')
|
||||
if session.is_lockable(post):
|
||||
if post.flags & Post.LOCKED_FLAG:
|
||||
actions.append(f'=> /unlock/{post.id} 🔓 Unlock comments\n')
|
||||
else:
|
||||
actions.append(f'=> /lock/{post.id} 🔒 Lock comments\n')
|
||||
if session.is_movable(post):
|
||||
actions.append(f'=> /edit/{post.id}/move/{session.get_token()} Move to subspace\n')
|
||||
if post.user != session.user.id and not session.is_user_mod and session.user.role != User.ADMIN:
|
||||
|
@ -288,7 +293,9 @@ def make_post_page_or_configure_feed(session):
|
|||
if arg2 == '/group':
|
||||
subspace = db.get_subspace(id=post.subspace)
|
||||
if session.c_user:
|
||||
page = f'# {session.c_user.avatar} u/{session.c_user.name}\n'
|
||||
page = f'# {session.c_user.avatar} {session.c_user.name}\n'
|
||||
if session.c_user.flair:
|
||||
page += f"[{session.c_user.flair}]\n"
|
||||
else:
|
||||
page = f'# {subspace.title()}\n'
|
||||
page += f'=> /{subspace.title()} {subspace.title()}\n'
|
||||
|
@ -351,7 +358,8 @@ def make_post_page(session, post):
|
|||
return 51, 'Not found'
|
||||
page += f'=> /help/deleted-post 🔒 Comment on a deleted post (ID:{post_id})\n\n'
|
||||
page += session.render_post(focused_cmt)
|
||||
page += f'\n=> /u/{focused_cmt.poster_name} {focused_cmt.poster_avatar} {focused_cmt.poster_name}\n'
|
||||
flair = f' [{focused_cmt.poster_flair}]' if focused_cmt.poster_flair else ''
|
||||
page += f'\n=> /u/{focused_cmt.poster_name} {focused_cmt.poster_avatar} {focused_cmt.poster_name}{flair}\n'
|
||||
page += f'{focused_cmt.age()}\n'
|
||||
|
||||
# Comment actions.
|
||||
|
@ -361,7 +369,7 @@ def make_post_page(session, post):
|
|||
if session.is_editable(focused_cmt):
|
||||
actions.append(f'=> /edit/{focused_cmt.id} ✏️ Edit\n')
|
||||
if post and session.user and not session.is_context_locked and \
|
||||
session.user.role != User.LIMITED:
|
||||
session.user.role != User.LIMITED and session.is_commenting_enabled(post):
|
||||
actions.append(f'=> /comment/{post.id} 💬 Comment\n')
|
||||
if session.is_thanks_enabled() and focused_cmt.user != user.id:
|
||||
actions.append(f'=> /thanks/{focused_cmt.id} 🙏 Give thanks\n')
|
||||
|
@ -429,7 +437,8 @@ def make_post_page(session, post):
|
|||
page += '\n'
|
||||
if post.tags:
|
||||
page += '### ' + post.tags + '\n'
|
||||
poster_link = f'=> /u/{post.poster_name} {post.poster_avatar} {post.poster_name}\n'
|
||||
flair = f" [{post.poster_flair}]" if post.poster_flair else ""
|
||||
poster_link = f'=> /u/{post.poster_name} {post.poster_avatar} {post.poster_name}{flair}\n'
|
||||
if session.is_context_tracker:
|
||||
page += f'=> /{session.context.title()} 🐞 Issue #{post.issueid} in {session.context.title()}\n'
|
||||
elif not session.c_user:
|
||||
|
@ -451,6 +460,8 @@ def make_post_page(session, post):
|
|||
listed.append(f'{r} {reactions[r]}')
|
||||
if listed:
|
||||
page += ' · ' + ' '.join(listed)
|
||||
if post.flags & Post.LOCKED_FLAG:
|
||||
page += '\n🔒 Locked'
|
||||
page += '\n'
|
||||
|
||||
# Post actions.
|
||||
|
@ -461,7 +472,7 @@ def make_post_page(session, post):
|
|||
page += f'=> /edit/{post.id} ✏️ Edit {kind}\n'
|
||||
elif session.is_title_editable(post):
|
||||
page += f'=> /edit/{post.id}/mod-title ✏️ Edit {kind} title\n'
|
||||
if session.user.role != User.LIMITED:
|
||||
if session.user.role != User.LIMITED and session.is_commenting_enabled(post):
|
||||
page += f'=> /comment/{post.id} 💬 Comment\n'
|
||||
|
||||
# Reactions.
|
||||
|
@ -567,10 +578,12 @@ def make_post_page(session, post):
|
|||
cmt.ymd_hm(tz=session.tz, date_fmt='%b %d', time_prefix='at ') if elapsed_hours < 24 * 180 else \
|
||||
cmt.ymd_hm(tz=session.tz, time_prefix='at ')
|
||||
|
||||
cmt_flair = f" [{cmt.poster_flair}]" if cmt.poster_flair else ""
|
||||
|
||||
if not session.is_archive:
|
||||
src = f'=> /u/{cmt.poster_name}/{cmt.id} {cmt.poster_avatar} {cmt.poster_name} · {comment_age}:\n'
|
||||
src = f'=> /u/{cmt.poster_name}/{cmt.id} {cmt.poster_avatar} {cmt.poster_name}{cmt_flair} · {comment_age}:\n'
|
||||
else:
|
||||
src = f'=> /u/{cmt.poster_name} {cmt.poster_avatar} {cmt.poster_name} · {comment_age}:\n'
|
||||
src = f'=> /u/{cmt.poster_name} {cmt.poster_avatar} {cmt.poster_name}{cmt_flair} · {comment_age}:\n'
|
||||
comment_body = session.render_post(cmt)
|
||||
src += comment_body
|
||||
|
||||
|
@ -615,6 +628,7 @@ def make_post_page(session, post):
|
|||
and session.user
|
||||
and session.user.role != User.LIMITED
|
||||
and post
|
||||
and session.is_commenting_enabled(post)
|
||||
and not session.is_context_locked
|
||||
and not display_order_desc
|
||||
and (is_comment_page or len(comments) >= 1)):
|
||||
|
@ -693,6 +707,8 @@ def make_feed_page(session):
|
|||
if c_user and (c_user.info or c_user.url):
|
||||
if c_user.info:
|
||||
topinfo += c_user.info + '\n'
|
||||
if c_user.flair:
|
||||
topinfo += f"[{c_user.flair}]\n"
|
||||
if c_user.url:
|
||||
topinfo += f'=> {c_user.url}\n'
|
||||
elif context:
|
||||
|
|
52
model.py
52
model.py
|
@ -250,12 +250,14 @@ class User:
|
|||
|
||||
FEED_MASK = HOME_FOLLOWED_FEED_FLAG | HOME_USERS_FEED_FLAG | HOME_NO_USERS_FEED_FLAG
|
||||
|
||||
def __init__(self, id, name, info, url, recovery, avatar, role, flags, notif, email, email_inter, \
|
||||
email_range, password, ts_password, ts_created, ts_active, sort_post, sort_cmt,
|
||||
def __init__(self, id, name, info, flair, url, recovery, avatar, role, flags, notif, \
|
||||
email, email_inter, email_range, \
|
||||
password, ts_password, ts_created, ts_active, sort_post, sort_cmt,
|
||||
timezone):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.info = info
|
||||
self.flair = flair
|
||||
self.url = url
|
||||
self.recovery = recovery
|
||||
self.avatar = avatar
|
||||
|
@ -350,16 +352,17 @@ class Post:
|
|||
TAG_POLL = 'poll'
|
||||
TAG_CLOSED = 'closed'
|
||||
|
||||
OMIT_FROM_FEED_FLAG = 0x1
|
||||
OMIT_FROM_ALL_FLAG = 0x2
|
||||
DISABLE_FEATURED_LINK = 0x4
|
||||
OMIT_FROM_FEED_FLAG = 0x1
|
||||
OMIT_FROM_ALL_FLAG = 0x2
|
||||
DISABLE_FEATURED_LINK_FLAG = 0x4
|
||||
LOCKED_FLAG = 0x8
|
||||
|
||||
SORT_CREATED, SORT_ACTIVE, SORT_HOTNESS = range(3)
|
||||
|
||||
def __init__(self, id, subspace, parent, user, issueid, title, flags, is_draft, is_pinned,
|
||||
num_cmts, num_likes, tags, ts_created, ts_edited, summary,
|
||||
sub_name=None, sub_owner=None, poster_avatar=None, poster_name=None, num_notifs=0,
|
||||
num_per_day=None, ts_comment=None):
|
||||
sub_name=None, sub_owner=None, poster_avatar=None, poster_name=None,
|
||||
poster_flair=None, num_notifs=0, num_per_day=None, ts_comment=None):
|
||||
self.id = id
|
||||
self.subspace = subspace
|
||||
self.parent = parent
|
||||
|
@ -380,6 +383,7 @@ class Post:
|
|||
self.sub_owner = sub_owner
|
||||
self.poster_avatar = poster_avatar
|
||||
self.poster_name = poster_name
|
||||
self.poster_flair = poster_flair
|
||||
self.num_notifs = num_notifs
|
||||
self.num_per_day = num_per_day
|
||||
|
||||
|
@ -491,6 +495,7 @@ class Database:
|
|||
db.execute("""CREATE TABLE IF NOT EXISTS users (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
name VARCHAR(30) UNIQUE,
|
||||
flair VARCHAR(30) DEFAULT '',
|
||||
info VARCHAR(1000) DEFAULT '',
|
||||
url VARCHAR(1000) DEFAULT '',
|
||||
recovery VARCHAR(1000) DEFAULT '',
|
||||
|
@ -755,7 +760,7 @@ class Database:
|
|||
WHERE {' AND '.join(cond)}""", values)
|
||||
users = []
|
||||
for (id, name, avatar, ts_created, ts_active) in cur:
|
||||
user = User(id, name, None, None, None,
|
||||
user = User(id, name, None, None, None, None,
|
||||
avatar, role, 0, 0, None, None, None, None, None,
|
||||
ts_created, ts_active, None, None, None)
|
||||
users.append(user)
|
||||
|
@ -786,6 +791,7 @@ class Database:
|
|||
u.id,
|
||||
u.name,
|
||||
u.info,
|
||||
u.flair,
|
||||
u.url,
|
||||
u.recovery,
|
||||
u.avatar,
|
||||
|
@ -807,10 +813,10 @@ class Database:
|
|||
JOIN subspaces s ON s.owner=u.id
|
||||
WHERE {' AND '.join(cond)}""", values)
|
||||
|
||||
for (id, name, info, url, recovery, avatar, role, flags, notif, email, email_inter,
|
||||
for (id, name, info, flair, url, recovery, avatar, role, flags, notif, email, email_inter,
|
||||
email_range, password, ts_password, ts_created, ts_active,
|
||||
sort_post, sort_cmt, timezone, user_subspace_id) in cur:
|
||||
user = User(id, name, info, url, recovery, avatar, role, flags, notif,
|
||||
user = User(id, name, info, flair, url, recovery, avatar, role, flags, notif,
|
||||
email, email_inter, email_range,
|
||||
password, ts_password,
|
||||
ts_created, ts_active,
|
||||
|
@ -860,7 +866,8 @@ class Database:
|
|||
|
||||
def update_user(self, user: Union[User, int],
|
||||
role=None,
|
||||
avatar=None, name=None, info=None, url=None, recovery=None,
|
||||
avatar=None, name=None, info=None, flair=None,
|
||||
url=None, recovery=None,
|
||||
email=None, email_inter=None, email_range=None,
|
||||
notif=None, flags=None,
|
||||
password=None, password_expiration_offset_minutes=0,
|
||||
|
@ -883,6 +890,9 @@ class Database:
|
|||
if info != None:
|
||||
stm.append('info=?')
|
||||
values.append(info)
|
||||
if flair != None:
|
||||
stm.append('flair=?')
|
||||
values.append(flair)
|
||||
if url != None:
|
||||
stm.append('url=?')
|
||||
values.append(url)
|
||||
|
@ -1226,8 +1236,8 @@ class Database:
|
|||
|
||||
mods = []
|
||||
for (id, avatar, name, ts_active) in cur:
|
||||
mods.append(User(id, name, None, None, None, avatar, None, None, None, None, None, None, None,
|
||||
None, None, ts_active, None, None, None))
|
||||
mods.append(User(id, name, None, None, None, None, avatar, None, None, None, None,
|
||||
None, None, None, None, None, ts_active, None, None, None))
|
||||
return mods
|
||||
|
||||
def modify_mods(self, subspace, actor=None, add=None, remove=None):
|
||||
|
@ -1319,7 +1329,7 @@ class Database:
|
|||
render = ''
|
||||
|
||||
# Use only the first link/attachment.
|
||||
if not post.flags & Post.DISABLE_FEATURED_LINK:
|
||||
if not post.flags & Post.DISABLE_FEATURED_LINK_FLAG:
|
||||
for seg in filter(lambda s: s.type in [Segment.LINK, Segment.ATTACHMENT], segments):
|
||||
# No web URLs in the feeds.
|
||||
if seg.url.lower().startswith('http'):
|
||||
|
@ -1762,6 +1772,8 @@ class Database:
|
|||
ts_range=None,
|
||||
limit=None,
|
||||
page=0):
|
||||
if type(subspace) is Subspace:
|
||||
subspace = subspace.id
|
||||
cur = self.conn.cursor()
|
||||
where_stm = []
|
||||
values = [notifs_for_user_id]
|
||||
|
@ -1795,7 +1807,7 @@ class Database:
|
|||
|
||||
if subspace != None:
|
||||
where_stm.append('p.subspace=?')
|
||||
values.append(subspace.id)
|
||||
values.append(subspace)
|
||||
PIN_ORDER = 'is_pinned DESC, '
|
||||
elif ts_range != None:
|
||||
where_stm.append('(UNIX_TIMESTAMP(p.ts_edited)>=? AND UNIX_TIMESTAMP(p.ts_edited)<?)')
|
||||
|
@ -1865,6 +1877,7 @@ class Database:
|
|||
sub1.owner, -- sub2.owner,
|
||||
u.avatar,
|
||||
u.name AS u_name,
|
||||
u.flair,
|
||||
(SELECT COUNT(notifs.id)
|
||||
FROM notifs
|
||||
WHERE notifs.dst=? AND notifs.post=p.id AND NOT notifs.is_hidden
|
||||
|
@ -1928,7 +1941,7 @@ class Database:
|
|||
posts = []
|
||||
for (id, subspace, parent, user, issueid, title, flags, is_draft, is_pinned,
|
||||
num_cmts, num_likes, tags, ts_created, ts_edited, ts_comment,
|
||||
summary, sub_name, sub_owner, poster_avatar, poster_name, num_notifs,
|
||||
summary, sub_name, sub_owner, poster_avatar, poster_name, flair, num_notifs,
|
||||
_num_people, _date_created, _row_num, num_per_day) in cur:
|
||||
posts.append(Post(id, subspace, parent, user, issueid,
|
||||
title,
|
||||
|
@ -1942,6 +1955,7 @@ class Database:
|
|||
sub_owner=sub_owner,
|
||||
poster_avatar=poster_avatar,
|
||||
poster_name=poster_name,
|
||||
poster_flair=flair,
|
||||
num_notifs=num_notifs,
|
||||
num_per_day=num_per_day))
|
||||
return posts
|
||||
|
@ -2726,16 +2740,16 @@ class Search:
|
|||
for pt in p_terms:
|
||||
values += [pt, pt, pt]
|
||||
cur.execute(f"""
|
||||
SELECT UNIX_TIMESTAMP(ts_active), id, name, avatar, info, url
|
||||
SELECT UNIX_TIMESTAMP(ts_active), id, name, avatar, info, flair, url
|
||||
FROM users
|
||||
WHERE {' AND '.join(cond)}
|
||||
ORDER BY ts_active DESC
|
||||
LIMIT {ulimit}
|
||||
OFFSET {ulimit * page_index}
|
||||
""", values)
|
||||
for (ts, id, name, avatar, info, url) in cur:
|
||||
for (ts, id, name, avatar, info, flair, url) in cur:
|
||||
self.results.append(((exact_match(name), ts),
|
||||
User(id, name, info, url, None, avatar, None, None, None,
|
||||
User(id, name, info, flair, url, None, avatar, None, None, None,
|
||||
None, None, None, None, None, ts, None, None, None, None)))
|
||||
|
||||
# Subspaces.
|
||||
|
|
19
user.py
19
user.py
|
@ -28,6 +28,23 @@ def user_actions(session):
|
|||
db.modify_likes(session.user, post, add=(action == 'like'))
|
||||
return 30, post.page_url()
|
||||
|
||||
elif req.path.startswith(session.path + 'lock/') or \
|
||||
req.path.startswith(session.path + 'unlock/'):
|
||||
if not user:
|
||||
return 60, 'Login required'
|
||||
if user.role == User.LIMITED:
|
||||
return 61, 'Not authorized'
|
||||
found = re.match(r'^(lock|unlock)/(\d+)$', req.path[len(session.path):])
|
||||
action = found.group(1)
|
||||
post_id = int(found.group(2))
|
||||
post = db.get_post(id=post_id)
|
||||
if not post:
|
||||
return 51, 'Not found'
|
||||
if not session.is_lockable(post):
|
||||
return 60, 'Not authorized'
|
||||
db.update_post(post, flags=post.flags ^ Post.LOCKED_FLAG)
|
||||
return 30, post.page_url() + '/more'
|
||||
|
||||
elif req.path.startswith(session.path + 'react/') or \
|
||||
req.path.startswith(session.path + 'unreact/'):
|
||||
if not user:
|
||||
|
@ -217,7 +234,7 @@ def user_actions(session):
|
|||
target_type = FOLLOW_POST if is_follow else MUTE_POST
|
||||
target_id = int(post_id)
|
||||
post = db.get_post(target_id)
|
||||
dst = post.page_url()
|
||||
dst = post.page_url() + '/more'
|
||||
else:
|
||||
target_type = FOLLOW_SUBSPACE if is_follow else MUTE_SUBSPACE
|
||||
sub_name = (u_sub if u_sub != None else s_sub)[2:]
|
||||
|
|
|
@ -66,7 +66,7 @@ class Emailer (threading.Thread):
|
|||
# Check that the current hour is not excluded.
|
||||
if is_hour_in_range(cur_hour, email_range):
|
||||
continue
|
||||
pending_notifs.append(User(id, name, None, None, None, None, None,
|
||||
pending_notifs.append(User(id, name, None, None, None, None, None, None,
|
||||
None, enabled_types, email, None,
|
||||
email_range, None, None, None, None,
|
||||
None, None, None))
|
||||
|
|
Loading…
Reference in New Issue