diff --git a/.gitignore b/.gitignore index aee51b3dc9..af0747b346 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,4 @@ package-lock.json local.txt *.scssc .idea/* +disablesignups diff --git a/drama/classes/award.py b/drama/classes/award.py index f8e3cc8359..fb62bf188f 100644 --- a/drama/classes/award.py +++ b/drama/classes/award.py @@ -3,18 +3,20 @@ from sqlalchemy import * from sqlalchemy.orm import relationship #from .mix_ins import * -from drama.__main__ import Base +from drama.__main__ import Base, app AWARDS = { "ban": { + "kind": "ban", "title": "1-Day Ban", "description": "Ban the author for a day.", "icon": "fas fa-gavel", "color": "text-danger" }, "shit": { + "kind": "shit", "title": "Literal Shitpost", - "description": "Let OP know how much their post sucks ass.", + "description": "Let OP know how much their post sucks ass. Flies will swarm their idiotic post. (flies only work on posts lol!!)", "icon": "fas fa-poop", "color": "text-black-50" } @@ -28,8 +30,8 @@ class AwardRelationship(Base): id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.id")) - submission_id = Column(Integer, ForeignKey("submissions.id")) - comment_id = Column(Integer, ForeignKey("comments.id")) + submission_id = Column(Integer, ForeignKey("submissions.id"), default=None) + comment_id = Column(Integer, ForeignKey("comments.id"), default=None) kind = Column(String(20)) user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", lazy="joined") @@ -44,6 +46,18 @@ class AwardRelationship(Base): lazy="joined" ) + @property + def given(self): + return bool(self.submission_id) or bool(self.comment_id) + @property def type(self): return AWARDS[self.kind] + + @property + def title(self): + return self.type['title'] + + @property + def class_list(self): + return self.type['icon']+' '+self.type['color'] diff --git a/drama/classes/comment.py b/drama/classes/comment.py index 6ac8639508..8a93e34b2c 100644 --- a/drama/classes/comment.py +++ b/drama/classes/comment.py @@ -67,7 +67,7 @@ class Comment(Base, Age_times, Scores, Stndrd, Fuzzing): parent_comment = relationship("Comment", remote_side=[id]) child_comments = relationship("Comment", remote_side=[parent_comment_id]) - #awards = relationship("AwardRelationship", lazy="joined") + awards = relationship("AwardRelationship", lazy="joined") # These are virtual properties handled as postgres functions server-side # There is no difference to SQLAlchemy, but they cannot be written to diff --git a/drama/classes/submission.py b/drama/classes/submission.py index 84eb029b90..900a977058 100644 --- a/drama/classes/submission.py +++ b/drama/classes/submission.py @@ -90,7 +90,7 @@ class Submission(Base, Stndrd, Age_times, Scores, Fuzzing): comment_count = Column(Integer, server_default=FetchedValue()) score = deferred(Column(Float, server_default=FetchedValue())) - #awards = relationship("AwardRelationship", lazy="joined") + awards = relationship("AwardRelationship", lazy="joined") def __init__(self, *args, **kwargs): @@ -284,6 +284,9 @@ class Submission(Base, Stndrd, Age_times, Scores, Fuzzing): return data + def has_award(self, kind): + return bool(len([x for x in self.awards if x.kind == kind])) + @property def voted(self): return self._voted if "_voted" in self.__dict__ else 0 diff --git a/drama/classes/user.py b/drama/classes/user.py index 4839a68324..e2c22fb814 100644 --- a/drama/classes/user.py +++ b/drama/classes/user.py @@ -104,6 +104,12 @@ class User(Base, Stndrd, Age_times): lazy="dynamic", primaryjoin="User.id==SaveRelationship.user_id") + awards = relationship( + "AwardRelationship", + lazy="dynamic", + primaryjoin="User.id==AwardRelationship.user_id" + ) + # properties defined as SQL server-side functions referral_count = deferred(Column(Integer, server_default=FetchedValue())) diff --git a/drama/routes/__init__.py b/drama/routes/__init__.py index 438666d820..bf40d037f2 100644 --- a/drama/routes/__init__.py +++ b/drama/routes/__init__.py @@ -12,4 +12,5 @@ from .settings import * from .static import * from .users import * from .votes import * -from .feeds import * \ No newline at end of file +from .feeds import * +from .awards import * \ No newline at end of file diff --git a/drama/routes/awards.py b/drama/routes/awards.py new file mode 100644 index 0000000000..79a6193fdf --- /dev/null +++ b/drama/routes/awards.py @@ -0,0 +1,211 @@ +from drama.__main__ import app +from drama.helpers.wrappers import * +from drama.helpers.alerts import * +from drama.helpers.get import * +from drama.classes.award import * +from flask import g, jsonify, request + + +def banaward_trigger(post=None, comment=None): + + author = post.author if post else comment.author + link = f"[this post]({post.permalink})" if post else f"[this comment]({comment.permalink})" + + if author.admin_level < 1: + if not author.is_suspended: + author.ban(reason="1-day ban award used", days=1) + + send_notification(1046, author, f"Your Drama account has been suspended for a day for {link}. It sucked and you should feel bad.") + elif author.unban_utc > 0: + author.unban_utc += 24*60*60 + g.db.add(author) + + send_notification(1046, author, + f"Your Drama account has been suspended for yet another day for {link}. Seriously man?") + + +ACTIONS = { + "ban": banaward_trigger +} + +ALLOW_MULTIPLE = ( + "ban", +) + + +@app.get("/api/awards") +@auth_required +def get_awards(v): + + return_value = list(AWARDS.values()) + + user_awards = v.awards + for val in return_value: + val['owned'] = len([x for x in user_awards if x.kind == val['kind'] and not x.given]) + + return jsonify(return_value) + + +@app.put("/api/post//awards") +@auth_required +@validate_formkey +def award_post(pid, v): + + if v.is_suspended and v.unban_utc == 0: + return jsonify({"error": "forbidden"}), 403 + + kind = request.form.get("kind", "") + + if kind not in AWARDS: + return jsonify({"error": "That award doesn't exist."}), 404 + + post_award = g.db.query(AwardRelationship).filter( + and_( + AwardRelationship.kind == kind, + AwardRelationship.user_id == v.id, + AwardRelationship.submission_id == None, + AwardRelationship.comment_id == None + ) + ).first() + + if not post_award: + return jsonify({"error": "You don't have that award."}), 404 + + post = g.db.query(Submission).filter_by(id=pid).first() + + if not post or post.is_banned or post.deleted_utc > 0: + return jsonify({"error": "That post doesn't exist or has been deleted or removed."}), 404 + + if post.author_id == v.id: + return jsonify({"error": "You can't award yourself."}), 403 + + existing_award = g.db.query(AwardRelationship).filter( + and_( + AwardRelationship.submission_id == post.id, + AwardRelationship.user_id == v.id, + AwardRelationship.kind == kind + ) + ).first() + + if existing_award and kind not in ALLOW_MULTIPLE: + return jsonify({"error": "You can't give that award multiple times to the same post."}), 409 + + post_award.submission_id = post.id + #print(f"give award to pid {post_award.submission_id} ({post.id})") + g.db.add(post_award) + + msg = f"@{v.username} has given your [post]({post.permalink}) the {AWARDS[kind]['title']} Award!" + + note = request.form.get("note", "") + if note: + msg += f"\n\n> {note}" + + send_notification(1046, post.author, msg) + + if kind in ACTIONS: + ACTIONS[kind](post=post) + + return "", 204 + + +@app.put("/api/comment//awards") +@auth_required +@validate_formkey +def award_comment(cid, v): + + if v.is_suspended and v.unban_utc == 0: + return jsonify({"error": "forbidden"}), 403 + + kind = request.form.get("kind", "") + + if kind not in AWARDS: + return jsonify({"error": "That award doesn't exist."}), 404 + + comment_award = g.db.query(AwardRelationship).filter( + and_( + AwardRelationship.kind == kind, + AwardRelationship.user_id == v.id, + AwardRelationship.submission_id == None, + AwardRelationship.comment_id == None + ) + ).first() + + if not comment_award: + return jsonify({"error": "You don't have that award."}), 404 + + c = g.db.query(Comment).filter_by(id=cid).first() + + if not c or c.is_banned or c.deleted_utc > 0: + return jsonify({"error": "That comment doesn't exist or has been deleted or removed."}), 404 + + if c.author_id == v.id: + return jsonify({"error": "You can't award yourself."}), 403 + + existing_award = g.db.query(AwardRelationship).filter( + and_( + AwardRelationship.comment_id == c.id, + AwardRelationship.user_id == v.id, + AwardRelationship.kind == kind + ) + ).first() + + if existing_award and kind not in ALLOW_MULTIPLE: + return jsonify({"error": "You can't give that award multiple times to the same comment."}), 409 + + comment_award.comment_id = c.id + g.db.add(comment_award) + + msg = f"@{v.username} has given your [comment]({c.permalink}) the {AWARDS[kind]['title']} Award!" + + note = request.form.get("note", "") + if note: + msg += f"\n\n> {note}" + + send_notification(1046, c.author, msg) + + if kind in ACTIONS: + ACTIONS[kind](comment=c) + + return "", 204 + +@app.get("/admin/user_award") +@auth_required +def admin_userawards_get(v): + + if v.admin_level < 6: + abort(403) + + return render_template("admin/user_award.html", awards=list(AWARDS.values()), v=v) + +@app.post("/admin/user_award") +@auth_required +@validate_formkey +def admin_userawards_post(v): + + if v.admin_level < 6: + abort(403) + + u = get_user(request.form.get("username", '1'), graceful=False, v=v) + + awards = [] + + latest = g.db.query(AwardRelationship).order_by(AwardRelationship.id.desc()).first() + thing = latest.id + + for key, value in request.form.items(): + if key not in AWARDS: + continue + + if value: + for x in range(int(value)): + thing += 1 + + awards.append(AwardRelationship( + id=thing, + user_id=u.id, + kind=key + )) + + g.db.bulk_save_objects(awards) + + return redirect(f'/@{u.username}') diff --git a/drama/templates/admin/admin_home.html b/drama/templates/admin/admin_home.html index ebfe2c2e44..0481b96a65 100644 --- a/drama/templates/admin/admin_home.html +++ b/drama/templates/admin/admin_home.html @@ -10,6 +10,7 @@

 

 Admin Tools

{% filter markdown %} +* [Grant User Award](/admin/user_award) * [Advanced Stats](/api/user_stat_data) * [Ban Domain](/admin/domain/enter%20domain%20here) * [Shadowbanned Users](/admin/shadowbanned) diff --git a/drama/templates/admin/user_award.html b/drama/templates/admin/user_award.html new file mode 100644 index 0000000000..b089690039 --- /dev/null +++ b/drama/templates/admin/user_award.html @@ -0,0 +1,66 @@ +{% extends "default.html" %} + +{% block title %} +Grant User Award +{% endblock %} + +{% block pagetype %}message{% endblock %} + +{% block content %} + + {% if error %} + + {% endif %} + {% if msg %} + + {% endif %} + +

+

+
User Award Grant
+ +
+ + + +
+ + + + + + + + + + + +{% for a in awards %} + + + + + +{% endfor %} +
IconTitleAmount
{{ a['title'] }}
+ + + +
+{% endblock %} diff --git a/drama/templates/award_modal.html b/drama/templates/award_modal.html new file mode 100644 index 0000000000..15d7a68461 --- /dev/null +++ b/drama/templates/award_modal.html @@ -0,0 +1,152 @@ + + + + + + + + \ No newline at end of file diff --git a/drama/templates/comments.html b/drama/templates/comments.html index dcf840383e..0564997ffa 100644 --- a/drama/templates/comments.html +++ b/drama/templates/comments.html @@ -130,7 +130,13 @@ {% if c.edited_utc %} · Edited {{c.edited_string}} {% endif %} - + + {% if c.awards %} + {% for a in c.awards[:5] %} + + {% endfor %} + {% endif %} + {% if c.is_banned and c.ban_reason %} @@ -241,14 +247,6 @@
  • Votes
  • - {% if v and v.id!=c.author_id and v.admin_level == 0 %} - {% if v.banawards > 0 %} -
  • Give ban award
  • - {% else %} -
  • Give ban award
  • - {% endif %} - {% endif %} - {% if v and c.id in v.saved_comment_idlist() %}
  • Unsave
  • {% else %} @@ -259,6 +257,11 @@
  • Reply
  • + {% if v.id!=c.author_id %} +
  • Give Award
  • + {% endif %} + {% endif %}
  • Context
  • Copy link
  • diff --git a/drama/templates/default.html b/drama/templates/default.html index ea7d3e1946..344f220731 100644 --- a/drama/templates/default.html +++ b/drama/templates/default.html @@ -408,6 +408,14 @@ } } + // award modal + + function awardModal(link) { + var target = document.getElementById("awardTarget"); + + target.value = link; + } + // Expand Images on Desktop function expandDesktopImage(image, link) { @@ -1072,6 +1080,7 @@ {% if v %} +{% include "award_modal.html" %} {% include "flag_post_modal.html" %} {% include "flag_comment_modal.html" %} {% include "gif_modal.html" %} diff --git a/drama/templates/submission.html b/drama/templates/submission.html index 559af91eb0..0c3a676007 100644 --- a/drama/templates/submission.html +++ b/drama/templates/submission.html @@ -116,12 +116,8 @@ - {% if v and v.id!=p.author_id and v.admin_level == 0 %} - {% if v.banawards > 0 %} - - {% else %} - - {% endif %} + {% if v and v.id!=p.author_id %} + {% endif %} {% if v and p.id in v.subscribed_idlist() %} @@ -189,6 +185,20 @@ {% endblock %} {% block content %} + +{% if p.has_award("shit") %} + + +{% endif %} +
    @@ -224,6 +234,12 @@ {% if p.edited_utc %}  Edited {{p.edited_string}}{% endif %}   {{p.views}} views + + {% if p.awards %} + {% for a in p.awards[:5] %} + + {% endfor %} + {% endif %}
    {% if p.realurl(v) %} @@ -308,12 +324,8 @@
  • Votes
  • - {% if v and v.id!=p.author_id and v.admin_level == 0 %} - {% if v.banawards > 0 %} -
  • Give ban award
  • - {% else %} -
  • Give ban award
  • - {% endif %} + {% if v and v.id!=p.author_id %} +
  • Give Award
  • {% endif %}
  • Copy link
  • diff --git a/drama/templates/submission_listing.html b/drama/templates/submission_listing.html index 740c1389a8..12d6b7fa45 100644 --- a/drama/templates/submission_listing.html +++ b/drama/templates/submission_listing.html @@ -145,6 +145,12 @@ {% if p.edited_utc %}  Edited {{p.edited_string}}{% endif %}   {{p.views}} views + {% if p.awards %} + {% for a in p.awards[:5] %} + + {% endfor %} + {% endif %} +
    @@ -168,12 +174,8 @@
  • Votes
  • - {% if v and v.id!=p.author_id and v.admin_level == 0 %} - {% if v.banawards > 0 %} -
  • Give ban award
  • - {% else %} -
  • Give ban award
  • - {% endif %} + {% if v and v.id!=p.author_id %} +
  • Give Award
  • {% endif %}
  • Copy link
  • @@ -353,12 +355,8 @@
      - {% if v and v.id!=p.author_id and v.admin_level == 0 %} - {% if v.banawards > 0 %} - - {% else %} - - {% endif %} + {% if v and v.id!=p.author_id %} +
    • Give Award
    • {% endif %} {% if v and p.id in v.subscribed_idlist() %}