From 672745ee6c980b3211035d4fbecd39fa8fed7277 Mon Sep 17 00:00:00 2001 From: justcool393 Date: Sat, 22 Jul 2023 17:34:08 -0700 Subject: [PATCH 1/8] combine 5 different post/comment filter state adjustment routes (#637) --- files/assets/js/comments_admin.js | 95 ++------- files/classes/mod_logs.py | 40 ++-- files/routes/admin/admin.py | 187 ++++-------------- .../component/comment/actions_desktop.html | 20 +- .../comment/actions_mobile_admin.html | 13 +- files/templates/component/post/actions.html | 15 +- .../component/post/actions_admin_mobile.html | 20 +- ...a23fe2f1515c_rename_approve_mod_actions.py | 25 +++ 8 files changed, 126 insertions(+), 289 deletions(-) create mode 100644 migrations/versions/2023_07_22_14_37_20_a23fe2f1515c_rename_approve_mod_actions.py diff --git a/files/assets/js/comments_admin.js b/files/assets/js/comments_admin.js index 5317a9e02..0f20ce187 100644 --- a/files/assets/js/comments_admin.js +++ b/files/assets/js/comments_admin.js @@ -1,78 +1,23 @@ -function removeCommentBackend(post_id) { - url="/remove_comment/"+post_id - - post(url) -} - -function approveCommentBackend(post_id) { - url="/unremove_comment/"+post_id - - post(url) -} - -function removeCommentDesktop(post_id,button1,button2) { - removeCommentBackend(post_id) - - try { - document.getElementById("comment-"+post_id+"-only").classList.add("banned"); - } catch(e) { - document.getElementById("context").classList.add("banned"); +function moderate(isPost, id, removing, removeButtonDesktopId, removeButtonMobileId, approveButtonDesktopId, approveButtonMobileId) { + const filterState = removing ? "removed" : "normal"; + if (isPost) { + filter_new_status(id, filterState); + } else { + filter_new_comment_status(id, filterState); } - - var button=document.getElementById("remove-"+post_id); - button.onclick=function(){approveCommentDesktop(post_id)}; - button.innerHTML='Approve' - - if (typeof button1 !== 'undefined') { - document.getElementById(button1).classList.toggle("d-md-inline-block"); - document.getElementById(button2).classList.toggle("d-md-inline-block"); - } -}; - -function approveCommentDesktop(post_id,button1,button2) { - approveCommentBackend(post_id) - - try { - document.getElementById("comment-"+post_id+"-only").classList.remove("banned"); - } catch(e) { - document.getElementById("context").classList.remove("banned"); - } - - var button=document.getElementById("remove-"+post_id); - button.onclick=function(){removeCommentDesktop(post_id)}; - button.innerHTML='Remove' - - if (typeof button1 !== 'undefined') { - document.getElementById(button1).classList.toggle("d-md-inline-block"); - document.getElementById(button2).classList.toggle("d-md-inline-block"); - } -} - - -function removeCommentMobile(post_id,button1,button2) { - removeCommentBackend(post_id) - - document.getElementById("comment-"+post_id+"-only").classList.add("banned"); - var button=document.getElementById("remove-"+post_id); - button.onclick=function(){approveCommentMobile(post_id)}; - button.innerHTML='Approve' - - if (typeof button1 !== 'undefined') { - document.getElementById(button1).classList.toggle("d-none"); - document.getElementById(button2).classList.toggle("d-none"); - } -}; - -function approveCommentMobile(post_id,button1,button2) { - approveCommentBackend(post_id) - - document.getElementById("comment-"+post_id+"-only").classList.remove("banned"); - var button=document.getElementById("remove-"+post_id); - button.onclick=function(){removeCommentMobile(post_id)}; - button.innerHTML='Remove' - - if (typeof button1 !== 'undefined') { - document.getElementById(button1).classList.toggle("d-none"); - document.getElementById(button2).classList.toggle("d-none"); + const removeButtonDesktop = document.getElementById(removeButtonDesktopId); + const removeButtonMobile = document.getElementById(removeButtonMobileId); + const approveButtonDesktop = document.getElementById(approveButtonDesktopId); + const approveButtonMobile = document.getElementById(approveButtonMobileId); + if (removing) { + removeButtonDesktop.classList.add("d-none"); + removeButtonMobile.classList.add("d-none"); + approveButtonDesktop.classList.remove("d-none"); + approveButtonMobile.classList.remove("d-none"); + } else { + removeButtonDesktop.classList.remove("d-none"); + removeButtonMobile.classList.remove("d-none"); + approveButtonDesktop.classList.add("d-none"); + approveButtonMobile.classList.add("d-none"); } } diff --git a/files/classes/mod_logs.py b/files/classes/mod_logs.py index 24047861e..245bb98fc 100644 --- a/files/classes/mod_logs.py +++ b/files/classes/mod_logs.py @@ -85,6 +85,26 @@ class ModAction(CreatedBase): return f"/log/{self.id}" ACTIONTYPES = { + 'approve_post': { + "str": 'approved post {self.target_link}', + "icon": 'fa-feather-alt', + "color": 'bg-success' + }, + 'approve_comment': { + "str": 'approved {self.target_link}', + "icon": 'fa-comment', + "color": 'bg-success' + }, + 'remove_post': { + "str": 'removed post {self.target_link}', + "icon": 'fa-feather-alt', + "color": 'bg-danger' + }, + 'remove_comment': { + "str": 'removed {self.target_link}', + "icon": 'fa-comment', + "color": 'bg-danger' + }, 'approve_app': { "str": 'approved an application by {self.target_link}', "icon": 'fa-robot', @@ -100,21 +120,11 @@ ACTIONTYPES = { "icon": 'fa-badge', "color": 'bg-danger' }, - 'remove_comment': { - "str": 'removed {self.target_link}', - "icon": 'fa-comment', - "color": 'bg-danger' - }, 'ban_domain': { "str": 'banned a domain', "icon": 'fa-globe', "color": 'bg-danger' }, - 'remove_post': { - "str": 'removed post {self.target_link}', - "icon": 'fa-feather-alt', - "color": 'bg-danger' - }, 'ban_user': { "str": 'banned user {self.target_link}', "icon": 'fa-user-slash', @@ -300,21 +310,11 @@ ACTIONTYPES = { "icon": 'fa-eye-slash', "color": 'bg-danger' }, - 'unremove_comment': { - "str": 'reinstated {self.target_link}', - "icon": 'fa-comment', - "color": 'bg-success' - }, 'unban_domain': { "str": 'unbanned a domain', "icon": 'fa-globe', "color": 'bg-success' }, - 'unremove_post': { - "str": 'reinstated post {self.target_link}', - "icon": 'fa-feather-alt', - "color": 'bg-success' - }, 'unban_user': { "str": 'unbanned user {self.target_link}', "icon": 'fa-user', diff --git a/files/routes/admin/admin.py b/files/routes/admin/admin.py index efedbf8e0..c2a8e88d1 100644 --- a/files/routes/admin/admin.py +++ b/files/routes/admin/admin.py @@ -272,14 +272,14 @@ def filtered_comments(v): # (also rename Unremove to Approve, sigh) @app.post("/admin/update_filter_status") @limiter.exempt -@admin_level_required(2) +@admin_level_required(PERMS['POST_COMMENT_MODERATION']) def update_filter_status(v): update_body = request.get_json() new_status = update_body.get('new_status') post_id = update_body.get('post_id') comment_id = update_body.get('comment_id') if new_status not in ['normal', 'removed', 'ignored']: - return { 'result': f'Status of {new_status} is not permitted' } + return {'result': f'Status of {new_status} is not permitted'}, 403 if new_status == 'normal': state_mod_new = StateMod.VISIBLE @@ -292,43 +292,45 @@ def update_filter_status(v): state_report_new = StateReport.IGNORED if post_id: - target = g.db.get(Submission, post_id) - old_status = target.state_mod - - # this could totally be one query but it would be kinda ugly - if state_mod_new is not None: - g.db.query(Submission).where(Submission.id == post_id) \ - .update({Submission.state_mod: state_mod_new, Submission.state_mod_set_by: v.username}) - g.db.query(Submission).where(Submission.id == post_id) \ - .update({Submission.state_report: state_report_new}) + target: Submission = get_post(post_id, graceful=True) + modlog_target_type: str = 'post' elif comment_id: - target = g.db.get(Comment, comment_id) - old_status = target.state_mod - - if state_mod_new is not None: - g.db.query(Comment).where(Comment.id == comment_id) \ - .update({Comment.state_mod: state_mod_new, Comment.state_mod_set_by: v.username}) - g.db.query(Comment).where(Comment.id == comment_id) \ - .update({Comment.state_report: state_report_new}) + target: Comment = get_comment(comment_id, graceful=True) + modlog_target_type: str = 'comment' else: - return { 'result': f'No valid item ID provided' } + return {"result": "No valid item ID provided"}, 404 + + if not target: + return {"result": "Item ID does not exist"}, 404 - if target is not None: - # If comment now visible, update state to reflect publication. - if (isinstance(target, Comment) - and old_status != StateMod.VISIBLE - and state_mod_new == StateMod.VISIBLE): - comment_on_publish(target) # XXX: can cause discrepancies if removal state ≠ filter state + old_status = target.state_mod - if (isinstance(target, Comment) - and old_status == StateMod.VISIBLE - and state_mod_new != StateMod.VISIBLE and state_mod_new is not None): - comment_on_unpublish(target) # XXX: can cause discrepancies if removal state ≠ filter state + if state_mod_new is not None: + target.state_mod = state_mod_new + target.state_mod_set_by = v.username + target.state_report = state_report_new - g.db.commit() - return { 'result': 'Update successful' } - else: - return { 'result': 'Item ID does not exist' } + making_visible: bool = old_status != StateMod.VISIBLE and state_mod_new == StateMod.VISIBLE + making_invisible: bool = old_status == StateMod.VISIBLE and state_mod_new != StateMod.VISIBLE and state_mod_new is not None + + if making_visible: + modlog_action: str = "approve" + if isinstance(target, Comment): comment_on_publish(target) + elif making_invisible: + modlog_action: str = "remove" + if isinstance(target, Comment): comment_on_unpublish(target) + + if making_visible or making_invisible: + g.db.add(ModAction( + kind=f"{modlog_action}_{modlog_target_type}", + user_id=v.id, + target_submission_id=target.id if isinstance(target, Submission) else None, + target_comment_id=target.id if isinstance(target, Comment) else None + )) + + g.db.commit() + invalidate_cache(frontlist=True) + return { 'result': 'Update successful' } @app.get("/admin/image_posts") @limiter.exempt @@ -1100,74 +1102,6 @@ def unban_user(user_id, v): else: return {"message": f"@{user.username} was unbanned!"} -@app.post("/remove_post/") -@limiter.exempt -@admin_level_required(2) -def remove_post(post_id, v): - post = g.db.query(Submission).filter_by(id=post_id).one_or_none() - - if not post: - abort(400) - - post.state_mod = StateMod.REMOVED - post.state_mod_set_by = v.username - post.stickied = None - post.is_pinned = False - g.db.add(post) - - - - ma=ModAction( - kind="remove_post", - user_id=v.id, - target_submission_id=post.id, - ) - g.db.add(ma) - - invalidate_cache(frontlist=True) - - v.coins += 1 - g.db.add(v) - - requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, json={'files': [f"{SITE_FULL}/logged_out/"]}, timeout=5) - - g.db.commit() - - return {"message": "Post removed!"} - - -@app.post("/unremove_post/") -@limiter.exempt -@admin_level_required(2) -def unremove_post(post_id, v): - post = g.db.query(Submission).filter_by(id=post_id).one_or_none() - - if not post: - abort(400) - - if post.state_mod != StateMod.VISIBLE: - ma=ModAction( - kind="unremove_post", - user_id=v.id, - target_submission_id=post.id, - ) - g.db.add(ma) - - post.state_mod = StateMod.VISIBLE - post.state_mod_set_by = v.username - - g.db.add(post) - - invalidate_cache(frontlist=True) - - v.coins -= 1 - g.db.add(v) - - g.db.commit() - - return {"message": "Post approved!"} - - @app.post("/distinguish/") @limiter.exempt @admin_level_required(1) @@ -1307,59 +1241,10 @@ def unsticky_comment(cid, v): return {"message": "Comment unpinned!"} -@app.post("/remove_comment/") -@limiter.exempt -@admin_level_required(2) -def api_remove_comment(c_id, v): - comment = g.db.query(Comment).filter_by(id=c_id).one_or_none() - if not comment: - abort(404) - - comment.state_mod = StateMod.REMOVED - comment.state_mod_set_by = v.username - comment_on_unpublish(comment) # XXX: can cause discrepancies if removal state ≠ filter state - ma=ModAction( - kind="remove_comment", - user_id=v.id, - target_comment_id=comment.id, - ) - g.db.add(ma) - g.db.commit() - return {"message": "Comment removed!"} - - -@app.post("/unremove_comment/") -@limiter.exempt -@admin_level_required(2) -def api_unremove_comment(c_id, v): - comment = g.db.query(Comment).filter_by(id=c_id).one_or_none() - if not comment: abort(404) - - if comment.state_mod == StateMod.REMOVED: - ma=ModAction( - kind="unremove_comment", - user_id=v.id, - target_comment_id=comment.id, - ) - g.db.add(ma) - - comment.state_mod = StateMod.VISIBLE - comment.state_mod_set_by = v.username - comment_on_publish(comment) # XXX: can cause discrepancies if removal state ≠ filter state - - g.db.add(comment) - - g.db.commit() - - return {"message": "Comment approved!"} - - @app.post("/distinguish_comment/") @limiter.exempt @admin_level_required(1) def admin_distinguish_comment(c_id, v): - - comment = get_comment(c_id, v=v) if comment.author_id != v.id: abort(403) diff --git a/files/templates/component/comment/actions_desktop.html b/files/templates/component/comment/actions_desktop.html index 0bf3b59e3..a93c8b647 100644 --- a/files/templates/component/comment/actions_desktop.html +++ b/files/templates/component/comment/actions_desktop.html @@ -19,10 +19,12 @@ {% endif %} {% endif %} -{% if v and v.admin_level >= 2 and c.state_mod == StateMod.FILTERED %} - - -{% endif %} +{%- if v and v.admin_level >= PERMS['POST_COMMENT_MODERATION'] -%} + {%- set show_approve = c.state_mod != StateMod.VISIBLE or "/reported/" in request.path -%} + {%- set show_remove = c.state_mod != StateMod.REMOVED -%} + @@ -45,16 +47,6 @@ {% endif %} {% endif %} - {% if v.admin_level >= 2 %} - {% if "/reported/" in request.path %} - - - {% else %} - - - {% endif %} - {% endif %} - {% if c.parent_submission and (c.author_id==v.id or v.admin_level >= 2) %} diff --git a/files/templates/component/comment/actions_mobile_admin.html b/files/templates/component/comment/actions_mobile_admin.html index f906f1c45..bfe72e099 100644 --- a/files/templates/component/comment/actions_mobile_admin.html +++ b/files/templates/component/comment/actions_mobile_admin.html @@ -27,13 +27,12 @@ Unban user {% endif %} - {% if "/reported/" in request.path %} - Remove - Approve - {% else %} - Remove - Approve - {% endif %} + {%- if v and v.admin_level >= PERMS['POST_COMMENT_MODERATION'] -%} + {%- set show_approve = c.state_mod != StateMod.VISIBLE or "/reported/" in request.path -%} + {%- set show_remove = c.state_mod == StateMod.VISIBLE -%} + Remove + Approve + {%- endif -%} {% if c.oauth_app %} API App diff --git a/files/templates/component/post/actions.html b/files/templates/component/post/actions.html index c2fd70287..ec7beed93 100644 --- a/files/templates/component/post/actions.html +++ b/files/templates/component/post/actions.html @@ -58,15 +58,14 @@ Unmark club {% endif %} #} - {% if v.admin_level > 1 %} - {% if "/reported/" in request.path %} - {% if v.id != p.author.id %}Remove{% endif %} - Approve - {% else %} - {% if v.id != p.author.id %}Remove{% endif %} - Approve - {% endif %} + {%- if v and v.admin_level >= PERMS['POST_COMMENT_MODERATION'] -%} + {%- set show_approve = p.state_mod != StateMod.VISIBLE or "/reported/" in request.path -%} + {%- set show_remove = p.state_mod == StateMod.VISIBLE -%} + Remove + Approve + {%- endif -%} + {% if v.admin_level >= 2 %} {% if p.oauth_app %} API App {% endif %} diff --git a/files/templates/component/post/actions_admin_mobile.html b/files/templates/component/post/actions_admin_mobile.html index c8170e313..e043bcfb1 100644 --- a/files/templates/component/post/actions_admin_mobile.html +++ b/files/templates/component/post/actions_admin_mobile.html @@ -20,21 +20,14 @@ #} - - {% if "/reported/" in request.path %} - - - {% else %} - - - {% endif %} - - {% if v and v.admin_level >= 2 and p.state_mod == StateMod.FILTERED %} - @@ -47,7 +40,6 @@ {% endif %} - diff --git a/migrations/versions/2023_07_22_14_37_20_a23fe2f1515c_rename_approve_mod_actions.py b/migrations/versions/2023_07_22_14_37_20_a23fe2f1515c_rename_approve_mod_actions.py new file mode 100644 index 000000000..2b799ee20 --- /dev/null +++ b/migrations/versions/2023_07_22_14_37_20_a23fe2f1515c_rename_approve_mod_actions.py @@ -0,0 +1,25 @@ +"""Rename approve mod actions + +Revision ID: a23fe2f1515c +Revises: 7ae4658467d7 +Create Date: 2023-07-22 14:37:20.485816+00:00 + +""" +from alembic import op + + +# revision identifiers, used by Alembic. +revision = 'a23fe2f1515c' +down_revision = '7ae4658467d7' +branch_labels = None +depends_on = None + + +def upgrade(): + op.execute("UPDATE modactions SET kind='approve_post' WHERE kind='unremove_post';") + op.execute("UPDATE modactions SET kind='approve_comment' WHERE kind='unremove_comment';") + + +def downgrade(): + op.execute("UPDATE modactions SET kind='unremove_post' WHERE kind='approve_post';") + op.execute("UPDATE modactions SET kind='unremove_comment' WHERE kind='approve_comment';") From 4ff52b5ac03fa398ef3589ea43b7ec67180f9f33 Mon Sep 17 00:00:00 2001 From: sovejero Date: Sat, 22 Jul 2023 21:08:39 -0300 Subject: [PATCH 2/8] fix header dropdown menu sidescroll --- files/assets/css/main.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/assets/css/main.css b/files/assets/css/main.css index 9edb1e782..3039c0079 100644 --- a/files/assets/css/main.css +++ b/files/assets/css/main.css @@ -5134,7 +5134,7 @@ th, td { } #account-menu-header, #account-menu { - min-width: 10em; + min-width: 13em; } .navigation-secondary-link { From 7e68277eb63e9f0dd7a4e710e3a05b243cde714d Mon Sep 17 00:00:00 2001 From: justcool393 Date: Sat, 22 Jul 2023 17:47:44 -0700 Subject: [PATCH 3/8] Don't show users post content from users they've blocked (#639) --- files/classes/visstate.py | 3 ++- files/helpers/content.py | 5 ++++- files/routes/votes.py | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/files/classes/visstate.py b/files/classes/visstate.py index 50d1b754f..a0bfd9fc0 100644 --- a/files/classes/visstate.py +++ b/files/classes/visstate.py @@ -64,13 +64,14 @@ class VisibilityState: op_name_safe=target.author_name ) - def moderated_body(self, v: User | None) -> str | None: + def moderated_body(self, v: User | None, is_blocking: bool=False) -> str | None: if v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] \ or v.id == self.op_id): return None if self.deleted: return 'Deleted' if self.appear_removed(v): return 'Removed' if self.filtered: return 'Filtered' + if is_blocking: return f'You are blocking @{self.op_name_safe}' return None def visibility_and_message(self, v: User | None, is_blocking: bool) -> tuple[bool, str]: diff --git a/files/helpers/content.py b/files/helpers/content.py index 447acaf53..f6e913c1d 100644 --- a/files/helpers/content.py +++ b/files/helpers/content.py @@ -87,7 +87,10 @@ def canonicalize_url2(url:str, *, httpsify:bool=False) -> urllib.parse.ParseResu def body_displayed(target:Submittable, v:Optional[User], is_html:bool) -> str: - moderated:Optional[str] = target.visibility_state.moderated_body(v) + moderated:Optional[str] = target.visibility_state.moderated_body( + v=v, + is_blocking=getattr(target, 'is_blocking', False) + ) if moderated: return moderated body = target.body_html if is_html else target.body diff --git a/files/routes/votes.py b/files/routes/votes.py index 4fcc518e6..bbc949867 100644 --- a/files/routes/votes.py +++ b/files/routes/votes.py @@ -65,7 +65,8 @@ def api_vote_post(post_id, new, v): new = int(new) # get the post - post = get_post(post_id) + post = get_post(post_id, v=v) + if getattr(post, 'is_blocking', False): abort(403, "Can't vote on things from users you've blocked") # get the old vote, if we have one vote = g.db.query(Vote).filter_by(user_id=v.id, submission_id=post.id).one_or_none() @@ -132,7 +133,8 @@ def api_vote_comment(comment_id, new, v): new = int(new) # get the comment - comment = get_comment(comment_id) + comment = get_comment(comment_id, v=v) + if getattr(comment, 'is_blocking', False): abort(403, "Can't vote on things from users you've blocked") # get the old vote, if we have one vote = g.db.query(CommentVote).filter_by(user_id=v.id, comment_id=comment.id).one_or_none() From 2541737833f541ba4bcb85a474762f2669d121a9 Mon Sep 17 00:00:00 2001 From: justcool393 Date: Sat, 22 Jul 2023 17:50:39 -0700 Subject: [PATCH 4/8] remove extra divs (it seems we never needed them in the first place?) (#627) --- files/templates/settings_profile.html | 451 +++++++++++++------------- 1 file changed, 221 insertions(+), 230 deletions(-) diff --git a/files/templates/settings_profile.html b/files/templates/settings_profile.html index d1837615a..0ccbdc142 100644 --- a/files/templates/settings_profile.html +++ b/files/templates/settings_profile.html @@ -7,52 +7,50 @@

Theme

-
-
- -
-
-
- - -
- Enable if you would like to display images and videos in full size on the frontpage. +
+
+ +
+
+
+ +
+ Enable if you would like to display images and videos in full size on the frontpage. +
+
+ +
+
+
- -
-
- -
- -
-
- - -
- Enable if you would like to highlight comments made after the last time you visited a thread. +
+
+ +
+ Enable if you would like to highlight comments made after the last time you visited a thread.
+
- -
-
- -
-
-

Change the theme for the website.

-
- + {% for entry in THEMES %} + + {% endfor %} -
- Themes are not officially supported. If you run into an issue, please report it or submit a pull request.
+ Themes are not officially supported. If you run into an issue, please report it or submit a pull request. +
@@ -77,8 +75,8 @@
-

Profile Banner

+

Profile Banner

@@ -112,204 +110,197 @@ - {{v.referral_count}} + {{v.referral_count}} -
-
Share this link with a friend. {% if v.referral_count==0 %} When they sign up, you'll get the bronze recruitment badge.{% elif v.referral_count<10 %} When you refer 10 friends, you'll receive the silver recruitment badge.{% elif v.referral_count<100 %} When you refer 100 friends, you'll receive the gold recruitment badge.{% endif %}
-
+
-
- -

RSS Feed

-

Subscribe to the {{SITE_TITLE}} RSS feed.

-
-
-
- -
You can change the feed by replacing "new" with whatever sorting you want and "all" with whatever time filter you want.
-
+
+ Share this link with a friend. {% if v.referral_count==0 %} When they sign up, you'll get the bronze recruitment badge.{% elif v.referral_count<10 %} When you refer 10 friends, you'll receive the silver recruitment badge.{% elif v.referral_count<100 %} When you refer 100 friends, you'll receive the gold recruitment badge.{% endif %}
- -

Your Profile

-

Edit how others see you on {{SITE_TITLE}}.

-
-
- -
-

Your original username will always stay reserved for you: {{v.original_username}}

- -
- {{forms.formkey(v)}} - - 3-25 characters, including letters, numbers, _ , and - -
- -
-
-
-
- -
- -
-
- {{forms.formkey(v)}} - -
- Limit of 100 characters - -
-
-
-
- -
- -
-
- {{forms.formkey(v)}} - - {% for titlecolor in COLORS %} - - - {% endfor %} -
-
- -

Or type a color code:

-
-
- {{forms.formkey(v)}} - - -
-
- -
- - {% if v.verified %} -
- -
-
- {{forms.formkey(v)}} - - {% for verifiedcolor in COLORS %} - - - {% endfor %} - -
- -
- -

Or type a color code:

-
-
- {{forms.formkey(v)}} - - -
-
- -
- {% endif %} - -
- -
-
- {{forms.formkey(v)}} -
- -
-
- -   - -   - -   - -   - -
-

-										
- Limit of 1500 characters - -
-
-
-
- -
- -
-
- {{forms.formkey(v)}} -
- -
-

-										
- Limit of 500 characters - -
-
-
-
- -
-
- -
-
-
- - -
- This will hide your post and comment history from others. We will also ask search engines to not index your profile page. (Your content will still be accessible via direct link.) -
-
-
-
- -
-
-
- - -
- Prevent other users from following you. -
-
-
-
+ + +

RSS Feed

+

Subscribe to the {{SITE_TITLE}} RSS feed.

+
+
+
+ +
You can change the feed by replacing "new" with whatever sorting you want and "all" with whatever time filter you want.
+
+
+
+ +

Your Profile

+

Edit how others see you on {{SITE_TITLE}}.

+
+
+ +
+

Your original username will always stay reserved for you: {{v.original_username}}

+
+ {{forms.formkey(v)}} + + 3-25 characters, including letters, numbers, _ , and - +
+ +
+
+
+
+ +
+ +
+
+ {{forms.formkey(v)}} + +
+ Limit of 100 characters + +
+
+
+
+ +
+ +
+
+ {{forms.formkey(v)}} + + {% for titlecolor in COLORS %} + + + {% endfor %} +
+
+ +

Or type a color code:

+
+
+ {{forms.formkey(v)}} + + +
+
+
+ + {% if v.verified %} +
+ +
+
+ {{forms.formkey(v)}} + {% for verifiedcolor in COLORS %} + + + {% endfor %} +
+
+ +

Or type a color code:

+
+
+ {{forms.formkey(v)}} + + +
+
+
+ {% endif %} + +
+ +
+
+ {{forms.formkey(v)}} +
+ +
+
+ +   + +   + +   + +   + +
+

+							
+ Limit of 1500 characters + +
+
+
+
+ +
+ +
+
+ {{forms.formkey(v)}} +
+ +
+

+							
+ Limit of 500 characters + +
+
+
+
+
+
+ +
+
+
+ + +
+ This will hide your post and comment history from others. We will also ask search engines to not index your profile page. (Your content will still be accessible via direct link.) +
+
+
+
+ +
+
+
+ + +
+ Prevent other users from following you. +
+
+
- {% endblock %} From a5a344f08497c2259cb8e1ca364fd29f02a12149 Mon Sep 17 00:00:00 2001 From: justcool393 Date: Sat, 22 Jul 2023 17:52:09 -0700 Subject: [PATCH 5/8] fix duplicate `~new~` indicators being sent (#642) we also make the JS we're generating about 7% the size it was before. --- files/assets/js/comments.js | 20 +++++++++++++- files/templates/comments.html | 48 ++++++++++++++++----------------- files/templates/submission.html | 22 +++++++-------- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/files/assets/js/comments.js b/files/assets/js/comments.js index 966f2c02b..4e7c0a903 100644 --- a/files/assets/js/comments.js +++ b/files/assets/js/comments.js @@ -56,4 +56,22 @@ function expandMarkdown(t,id) { let val = t.getElementsByTagName('span')[0] if (val.innerHTML == 'View source') val.innerHTML = 'Hide source' else val.innerHTML = 'View source' -}; \ No newline at end of file +}; + +function commentsAddUnreadIndicator(commentIds) { + commentIds.forEach(element => { + const commentOnly = document.getElementById(`comment-${element}-only`); + if (!commentOnly) { + console.warn(`Couldn't find comment (comment ID ${element}) in page while attempting to add an unread indicator.`); + return; + } + if (commentOnly.classList.contains("unread")) return; + commentOnly.classList.add("unread"); + const commentUserInfo = document.getElementById(`comment-${element}`)?.querySelector(".comment-user-info"); + if (!commentUserInfo) { + console.warn(`Couldn't find comment user info (comment ID ${element}) in page while attempting to add an unread indicator.`); + return; + } + commentUserInfo.innerHTML += "~new~"; + }); +} diff --git a/files/templates/comments.html b/files/templates/comments.html index 879709ef6..793ec7d87 100644 --- a/files/templates/comments.html +++ b/files/templates/comments.html @@ -201,23 +201,23 @@ + {# See https://github.com/themotte/rDrama/pull/642#issuecomment-1646649781 for info on this section of the code #} -
{{u.username}}
-{% endif %} - {% endblock %} diff --git a/files/templates/userpage_submissions.html b/files/templates/userpage_submissions.html new file mode 100644 index 000000000..9cf790d18 --- /dev/null +++ b/files/templates/userpage_submissions.html @@ -0,0 +1,10 @@ +{% extends "userpage.html" %} +{% block userpage_content %} +
+
+
+ {% include "submission_listing.html" %} +
+
+
+{% endblock %} From b4b3e03dc75e3d5c8457ca247fbf84b688e6ab1b Mon Sep 17 00:00:00 2001 From: justcool393 Date: Mon, 24 Jul 2023 06:33:49 -0500 Subject: [PATCH 8/8] there was a typo introduced when the new statemod system was introduced. we fix that. --- files/routes/admin/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/routes/admin/admin.py b/files/routes/admin/admin.py index c2a8e88d1..866892053 100644 --- a/files/routes/admin/admin.py +++ b/files/routes/admin/admin.py @@ -811,7 +811,7 @@ def admin_removed_comments(v): try: page = int(request.values.get("page", 1)) except: page = 1 - ids = g.db.query(Comment.id).join(User, User.id == Comment.author_id).filter(or_(Comment.state_mode == StateMod.REMOVED, User.shadowbanned != None)).order_by(Comment.id.desc()).offset(25 * (page - 1)).limit(26).all() + ids = g.db.query(Comment.id).join(User, User.id == Comment.author_id).filter(or_(Comment.state_mod == StateMod.REMOVED, User.shadowbanned != None)).order_by(Comment.id.desc()).offset(25 * (page - 1)).limit(26).all() ids=[x[0] for x in ids]