Poll rework (#312)
* poll rework * forgot to do joinedload on comments * Fix logic errors with voting, SQL syntax. Kitchen sink commit from review of poll-rework changes: 1. Fix seed-db.sql syntax error. 2. Fix SQL patch file duplication of *submissions* tables rather than one set of submissions and one for comments. 3. Start makeshift SQL patch folder, since this is a large change that contributors may wish to apply to their local instances. 4. Fix checkbox (non-`exclusive`) polls being unable to be unchecked. For consistency with `exclusive` polls, they should. 5. Fix changing the option of an `exclusive` poll when both exclusive and non-exclusive options are present in one comment/ post causing the non-exclusive options to become unchecked. (which, by my reading of SQLAlchemy `Query.one_or_none()` really could break quite badly in some cases). * link relationships with their counterparts * small modification to poll unchecking Co-authored-by: TLSM <duolsm@outlook.com>remotes/1693045480750635534/spooky-22
parent
671588d41c
commit
d0d15c319a
|
@ -16,10 +16,12 @@ class AwardRelationship(Base):
|
||||||
kind = Column(String)
|
kind = Column(String)
|
||||||
awarded_utc = Column(Integer)
|
awarded_utc = Column(Integer)
|
||||||
|
|
||||||
user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", viewonly=True)
|
user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", back_populates="awards")
|
||||||
post = relationship("Submission", primaryjoin="AwardRelationship.submission_id==Submission.id", viewonly=True)
|
post = relationship("Submission", primaryjoin="AwardRelationship.submission_id==Submission.id", back_populates="awards")
|
||||||
comment = relationship("Comment", primaryjoin="AwardRelationship.comment_id==Comment.id", viewonly=True)
|
comment = relationship("Comment", primaryjoin="AwardRelationship.comment_id==Comment.id", back_populates="awards")
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<AwardRelationship(id={self.id})>"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
|
|
|
@ -29,8 +29,8 @@ class Badge(Base):
|
||||||
url = Column(String)
|
url = Column(String)
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
|
||||||
user = relationship("User", viewonly=True)
|
user = relationship("User", back_populates="badges")
|
||||||
badge = relationship("BadgeDef", primaryjoin="foreign(Badge.badge_id) == remote(BadgeDef.id)", viewonly=True)
|
badge = relationship("BadgeDef", primaryjoin="foreign(Badge.badge_id) == remote(BadgeDef.id)")
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs:
|
if "created_utc" not in kwargs:
|
||||||
|
|
|
@ -19,9 +19,10 @@ class OauthApp(Base):
|
||||||
description = Column(String)
|
description = Column(String)
|
||||||
author_id = Column(Integer, ForeignKey("users.id"))
|
author_id = Column(Integer, ForeignKey("users.id"))
|
||||||
|
|
||||||
author = relationship("User", viewonly=True)
|
author = relationship("User")
|
||||||
|
|
||||||
def __repr__(self): return f"<OauthApp(id={self.id})>"
|
def __repr__(self):
|
||||||
|
return f"<OauthApp(id={self.id})>"
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -36,7 +37,8 @@ class OauthApp(Base):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def permalink(self): return f"/admin/app/{self.id}"
|
def permalink(self):
|
||||||
|
return f"/admin/app/{self.id}"
|
||||||
|
|
||||||
@lazy
|
@lazy
|
||||||
def idlist(self, page=1):
|
def idlist(self, page=1):
|
||||||
|
@ -70,8 +72,11 @@ class ClientAuth(Base):
|
||||||
oauth_client = Column(Integer, ForeignKey("oauth_apps.id"), primary_key=True)
|
oauth_client = Column(Integer, ForeignKey("oauth_apps.id"), primary_key=True)
|
||||||
access_token = Column(String)
|
access_token = Column(String)
|
||||||
|
|
||||||
user = relationship("User", viewonly=True)
|
user = relationship("User")
|
||||||
application = relationship("OauthApp", viewonly=True)
|
application = relationship("OauthApp")
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<ClientAuth(user_id={self.user_id}, oauth_client={self.oauth_client})>"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
|
|
|
@ -76,14 +76,15 @@ class Comment(Base):
|
||||||
wordle_result = Column(String)
|
wordle_result = Column(String)
|
||||||
treasure_amount = Column(String)
|
treasure_amount = Column(String)
|
||||||
|
|
||||||
oauth_app = relationship("OauthApp", viewonly=True)
|
oauth_app = relationship("OauthApp")
|
||||||
post = relationship("Submission", viewonly=True)
|
post = relationship("Submission", back_populates="comments")
|
||||||
author = relationship("User", primaryjoin="User.id==Comment.author_id")
|
author = relationship("User", primaryjoin="User.id==Comment.author_id")
|
||||||
senttouser = relationship("User", primaryjoin="User.id==Comment.sentto", viewonly=True)
|
senttouser = relationship("User", primaryjoin="User.id==Comment.sentto")
|
||||||
parent_comment = relationship("Comment", remote_side=[id], viewonly=True)
|
parent_comment = relationship("Comment", remote_side=[id], back_populates="child_comments")
|
||||||
child_comments = relationship("Comment", lazy="dynamic", remote_side=[parent_comment_id], viewonly=True)
|
child_comments = relationship("Comment", remote_side=[parent_comment_id], back_populates="parent_comment")
|
||||||
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", viewonly=True)
|
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", back_populates="comment")
|
||||||
flags = relationship("CommentFlag", order_by="CommentFlag.created_utc", viewonly=True)
|
flags = relationship("CommentFlag", order_by="CommentFlag.created_utc")
|
||||||
|
options = relationship("CommentOption", order_by="CommentOption.id")
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs:
|
if "created_utc" not in kwargs:
|
||||||
|
@ -99,35 +100,6 @@ class Comment(Base):
|
||||||
def top_comment(self):
|
def top_comment(self):
|
||||||
return g.db.get(Comment, self.top_comment_id)
|
return g.db.get(Comment, self.top_comment_id)
|
||||||
|
|
||||||
@lazy
|
|
||||||
def poll_voted(self, v):
|
|
||||||
if v:
|
|
||||||
vote = g.db.query(CommentVote.vote_type).filter_by(user_id=v.id, comment_id=self.id).one_or_none()
|
|
||||||
if vote: return vote[0]
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
|
||||||
@lazy
|
|
||||||
def options(self):
|
|
||||||
return self.child_comments.filter_by(author_id=AUTOPOLLER_ID).order_by(Comment.id).all()
|
|
||||||
|
|
||||||
@property
|
|
||||||
@lazy
|
|
||||||
def choices(self):
|
|
||||||
return self.child_comments.filter_by(author_id=AUTOCHOICE_ID).order_by(Comment.id).all()
|
|
||||||
|
|
||||||
@lazy
|
|
||||||
def total_poll_voted(self, v):
|
|
||||||
if v:
|
|
||||||
for option in self.options:
|
|
||||||
if option.poll_voted(v): return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@lazy
|
|
||||||
def total_choice_voted(self, v):
|
|
||||||
if v:
|
|
||||||
return g.db.query(CommentVote).filter(CommentVote.user_id == v.id, CommentVote.comment_id.in_([x.id for x in self.choices])).first()
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
|
@ -239,8 +211,7 @@ class Comment(Base):
|
||||||
if not self.parent_submission:
|
if not self.parent_submission:
|
||||||
return [x for x in self.child_comments.order_by(Comment.id) if not x.author.shadowbanned]
|
return [x for x in self.child_comments.order_by(Comment.id) if not x.author.shadowbanned]
|
||||||
|
|
||||||
comments = self.child_comments.filter(Comment.author_id.notin_(poll_bots))
|
comments = self.child_comments
|
||||||
comments = sort_comments(sort, comments)
|
|
||||||
return [x for x in comments if not x.author.shadowbanned]
|
return [x for x in comments if not x.author.shadowbanned]
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,8 +221,7 @@ class Comment(Base):
|
||||||
if not self.parent_submission:
|
if not self.parent_submission:
|
||||||
return self.child_comments.order_by(Comment.id).all()
|
return self.child_comments.order_by(Comment.id).all()
|
||||||
|
|
||||||
comments = self.child_comments.filter(Comment.author_id.notin_(poll_bots))
|
return self.child_comments
|
||||||
return sort_comments(sort, comments).all()
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -405,27 +375,25 @@ class Comment(Base):
|
||||||
self.upvotes += amount
|
self.upvotes += amount
|
||||||
g.db.add(self)
|
g.db.add(self)
|
||||||
|
|
||||||
for c in self.options:
|
if self.options:
|
||||||
body += f'<div class="custom-control"><input type="checkbox" class="custom-control-input" id="{c.id}" name="option"'
|
curr = [x for x in self.options if x.exclusive and x.voted(v)]
|
||||||
if c.poll_voted(v): body += " checked"
|
if curr: curr = " value=" + str(curr[0].id)
|
||||||
if v: body += f''' onchange="poll_vote('{c.id}', '{self.id}')"'''
|
|
||||||
else: body += f''' onchange="poll_vote_no_v('{c.id}', '{self.id}')"'''
|
|
||||||
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html}<span class="presult-{self.id}'''
|
|
||||||
if not self.total_poll_voted(v): body += ' d-none'
|
|
||||||
body += f'"> - <a href="/votes?link=t3_{c.id}"><span id="poll-{c.id}">{c.upvotes}</span> votes</a></span></label></div>'
|
|
||||||
|
|
||||||
if self.choices:
|
|
||||||
curr = self.total_choice_voted(v)
|
|
||||||
if curr: curr = " value=" + str(curr.comment_id)
|
|
||||||
else: curr = ''
|
else: curr = ''
|
||||||
body += f'<input class="d-none" id="current-{self.id}"{curr}>'
|
body += f'<input class="d-none" id="current-{self.id}"{curr}>'
|
||||||
|
|
||||||
for c in self.choices:
|
for c in self.options:
|
||||||
body += f'''<div class="custom-control"><input name="choice-{self.id}" autocomplete="off" class="custom-control-input" type="radio" id="{c.id}" onchange="choice_vote('{c.id}','{self.id}')"'''
|
if c.exclusive:
|
||||||
if c.poll_voted(v): body += " checked "
|
body += f'''<div class="custom-control"><input name="choice-{self.id}" autocomplete="off" class="custom-control-input" type="radio" id="{c.id}" onchange="choice_vote('{c.id}','{self.id}','comment')"'''
|
||||||
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html}<span class="presult-{self.id}'''
|
if c.voted(v): body += " checked "
|
||||||
if not self.total_choice_voted(v): body += ' d-none'
|
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html}<span class="presult-{self.id}'''
|
||||||
body += f'"> - <a href="/votes?link=t3_{c.id}"><span id="choice-{c.id}">{c.upvotes}</span> votes</a></span></label></div>'
|
body += f'"> - <a href="/votes/comment/option/{c.id}"><span id="choice-{c.id}">{c.upvotes}</span> votes</a></span></label></div>'
|
||||||
|
else:
|
||||||
|
body += f'<div class="custom-control"><input type="checkbox" class="custom-control-input" id="{c.id}" name="option"'
|
||||||
|
if c.voted(v): body += " checked"
|
||||||
|
if v: body += f''' onchange="poll_vote('{c.id}', 'comment')"'''
|
||||||
|
else: body += f''' onchange="poll_vote_no_v('{c.id}', '{self.id}')"'''
|
||||||
|
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html}<span class="presult-{self.id}'''
|
||||||
|
body += f'"> - <a href="/votes/comment/option/{c.id}"><span id="poll-{c.id}">{c.upvotes}</span> votes</a></span></label></div>'
|
||||||
|
|
||||||
if self.author.sig_html and (self.author_id == MOOSE_ID or (not self.ghost and not (v and (v.sigs_disabled or v.poor)))):
|
if self.author.sig_html and (self.author_id == MOOSE_ID or (not self.ghost and not (v and (v.sigs_disabled or v.poor)))):
|
||||||
body += f"<hr>{self.author.sig_html}"
|
body += f"<hr>{self.author.sig_html}"
|
||||||
|
|
|
@ -5,4 +5,7 @@ class BannedDomain(Base):
|
||||||
|
|
||||||
__tablename__ = "banneddomains"
|
__tablename__ = "banneddomains"
|
||||||
domain = Column(String, primary_key=True)
|
domain = Column(String, primary_key=True)
|
||||||
reason = Column(String)
|
reason = Column(String)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<BannedDomain(domain={self.domain})>"
|
|
@ -9,7 +9,7 @@ class Exile(Base):
|
||||||
sub = Column(String, ForeignKey("subs.name"), primary_key=True)
|
sub = Column(String, ForeignKey("subs.name"), primary_key=True)
|
||||||
exiler_id = Column(Integer, ForeignKey("users.id"))
|
exiler_id = Column(Integer, ForeignKey("users.id"))
|
||||||
|
|
||||||
exiler = relationship("User", primaryjoin="User.id==Exile.exiler_id", viewonly=True)
|
exiler = relationship("User", primaryjoin="User.id==Exile.exiler_id")
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Exile(user_id={self.user_id}, sub={self.sub})>"
|
return f"<Exile(user_id={self.user_id}, sub={self.sub})>"
|
|
@ -15,7 +15,7 @@ class Flag(Base):
|
||||||
reason = Column(String)
|
reason = Column(String)
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
|
||||||
user = relationship("User", primaryjoin = "Flag.user_id == User.id", uselist = False, viewonly=True)
|
user = relationship("User", primaryjoin = "Flag.user_id == User.id", uselist = False)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
@ -48,7 +48,7 @@ class CommentFlag(Base):
|
||||||
reason = Column(String)
|
reason = Column(String)
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
|
||||||
user = relationship("User", primaryjoin = "CommentFlag.user_id == User.id", uselist = False, viewonly=True)
|
user = relationship("User", primaryjoin = "CommentFlag.user_id == User.id", uselist = False)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
|
|
@ -9,8 +9,8 @@ class Follow(Base):
|
||||||
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
|
||||||
user = relationship("User", uselist=False, primaryjoin="User.id==Follow.user_id", viewonly=True)
|
user = relationship("User", uselist=False, primaryjoin="User.id==Follow.user_id", back_populates="following")
|
||||||
target = relationship("User", primaryjoin="User.id==Follow.target_id", viewonly=True)
|
target = relationship("User", uselist=False, primaryjoin="User.id==Follow.target_id", back_populates="followers")
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
|
|
@ -15,6 +15,9 @@ class Lottery(Base):
|
||||||
tickets_sold = Column(Integer, default=0)
|
tickets_sold = Column(Integer, default=0)
|
||||||
winner_id = Column(Integer, ForeignKey("users.id"))
|
winner_id = Column(Integer, ForeignKey("users.id"))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Lottery(id={self.id})>"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def timeleft(self):
|
def timeleft(self):
|
||||||
|
|
|
@ -18,9 +18,9 @@ class ModAction(Base):
|
||||||
_note=Column(String)
|
_note=Column(String)
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
|
||||||
user = relationship("User", primaryjoin="User.id==ModAction.user_id", viewonly=True)
|
user = relationship("User", primaryjoin="User.id==ModAction.user_id")
|
||||||
target_user = relationship("User", primaryjoin="User.id==ModAction.target_user_id", viewonly=True)
|
target_user = relationship("User", primaryjoin="User.id==ModAction.target_user_id")
|
||||||
target_post = relationship("Submission", viewonly=True)
|
target_post = relationship("Submission")
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
|
|
@ -12,8 +12,8 @@ class Notification(Base):
|
||||||
read = Column(Boolean, default=False)
|
read = Column(Boolean, default=False)
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
|
||||||
comment = relationship("Comment", viewonly=True)
|
comment = relationship("Comment")
|
||||||
user = relationship("User", viewonly=True)
|
user = relationship("User")
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
from sqlalchemy import *
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
from files.__main__ import Base
|
||||||
|
from files.helpers.lazy import lazy
|
||||||
|
import time
|
||||||
|
|
||||||
|
class SubmissionOption(Base):
|
||||||
|
|
||||||
|
__tablename__ = "submission_options"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
submission_id = Column(Integer, ForeignKey("submissions.id"))
|
||||||
|
body_html = Column(Text)
|
||||||
|
exclusive = Column(Boolean)
|
||||||
|
|
||||||
|
votes = relationship("SubmissionOptionVote")
|
||||||
|
post = relationship("Submission", back_populates="options")
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<SubmissionOption(id={self.id})>"
|
||||||
|
|
||||||
|
@property
|
||||||
|
@lazy
|
||||||
|
def upvotes(self):
|
||||||
|
return len(self.votes)
|
||||||
|
|
||||||
|
@lazy
|
||||||
|
def voted(self, v):
|
||||||
|
return v.id in [x.user_id for x in self.votes]
|
||||||
|
|
||||||
|
|
||||||
|
class SubmissionOptionVote(Base):
|
||||||
|
|
||||||
|
__tablename__ = "submission_option_votes"
|
||||||
|
|
||||||
|
option_id = Column(Integer, ForeignKey("submission_options.id"), primary_key=True)
|
||||||
|
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
||||||
|
created_utc = Column(Integer)
|
||||||
|
submission_id = Column(Integer, ForeignKey("submissions.id"))
|
||||||
|
|
||||||
|
user = relationship("User")
|
||||||
|
option = relationship("SubmissionOption")
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<SubmissionOptionVote(option_id={self.option_id}, user_id={self.user_id})>"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_datetime(self):
|
||||||
|
return str(time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(self.created_utc)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CommentOption(Base):
|
||||||
|
|
||||||
|
__tablename__ = "comment_options"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
comment_id = Column(Integer, ForeignKey("comments.id"))
|
||||||
|
body_html = Column(Text)
|
||||||
|
exclusive = Column(Boolean)
|
||||||
|
|
||||||
|
votes = relationship("CommentOptionVote")
|
||||||
|
post = relationship("Comment", back_populates="options")
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<CommentOption(id={self.id})>"
|
||||||
|
|
||||||
|
@property
|
||||||
|
@lazy
|
||||||
|
def upvotes(self):
|
||||||
|
return len(self.votes)
|
||||||
|
|
||||||
|
@lazy
|
||||||
|
def voted(self, v):
|
||||||
|
return v.id in [x.user_id for x in self.votes]
|
||||||
|
|
||||||
|
|
||||||
|
class CommentOptionVote(Base):
|
||||||
|
|
||||||
|
__tablename__ = "comment_option_votes"
|
||||||
|
|
||||||
|
option_id = Column(Integer, ForeignKey("comment_options.id"), primary_key=True)
|
||||||
|
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
||||||
|
created_utc = Column(Integer)
|
||||||
|
comment_id = Column(Integer, ForeignKey("comments.id"))
|
||||||
|
|
||||||
|
user = relationship("User")
|
||||||
|
option = relationship("CommentOption")
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<CommentOptionVote(option_id={self.option_id}, user_id={self.user_id})>"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_datetime(self):
|
||||||
|
return str(time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(self.created_utc)))
|
|
@ -10,6 +10,8 @@ class SaveRelationship(Base):
|
||||||
user_id=Column(Integer, ForeignKey("users.id"), primary_key=True)
|
user_id=Column(Integer, ForeignKey("users.id"), primary_key=True)
|
||||||
submission_id=Column(Integer, ForeignKey("submissions.id"), primary_key=True)
|
submission_id=Column(Integer, ForeignKey("submissions.id"), primary_key=True)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<SaveRelationship(user_id={self.user_id}, submission_id={self.submission_id})>"
|
||||||
|
|
||||||
|
|
||||||
class CommentSaveRelationship(Base):
|
class CommentSaveRelationship(Base):
|
||||||
|
@ -17,4 +19,7 @@ class CommentSaveRelationship(Base):
|
||||||
__tablename__="comment_save_relationship"
|
__tablename__="comment_save_relationship"
|
||||||
|
|
||||||
user_id=Column(Integer, ForeignKey("users.id"), primary_key=True)
|
user_id=Column(Integer, ForeignKey("users.id"), primary_key=True)
|
||||||
comment_id=Column(Integer, ForeignKey("comments.id"), primary_key=True)
|
comment_id=Column(Integer, ForeignKey("comments.id"), primary_key=True)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<CommentSaveRelationship(user_id={self.user_id}, comment_id={self.comment_id})>"
|
|
@ -19,10 +19,8 @@ class Sub(Base):
|
||||||
bannerurl = Column(String)
|
bannerurl = Column(String)
|
||||||
css = Column(String)
|
css = Column(String)
|
||||||
|
|
||||||
blocks = relationship("SubBlock",
|
blocks = relationship("SubBlock", primaryjoin="SubBlock.sub==Sub.name")
|
||||||
primaryjoin="SubBlock.sub==Sub.name", viewonly=True)
|
followers = relationship("SubSubscription", primaryjoin="SubSubscription.sub==Sub.name")
|
||||||
followers = relationship("SubSubscription",
|
|
||||||
primaryjoin="SubSubscription.sub==Sub.name", viewonly=True)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Sub(name={self.name})>"
|
return f"<Sub(name={self.name})>"
|
||||||
|
|
|
@ -16,6 +16,7 @@ from .saves import SaveRelationship
|
||||||
from .sub import *
|
from .sub import *
|
||||||
from .subscriptions import *
|
from .subscriptions import *
|
||||||
from .votes import CommentVote
|
from .votes import CommentVote
|
||||||
|
from .polls import *
|
||||||
from flask import g
|
from flask import g
|
||||||
|
|
||||||
def sort_posts(sort, posts):
|
def sort_posts(sort, posts):
|
||||||
|
@ -72,12 +73,13 @@ class Submission(Base):
|
||||||
new = Column(Boolean)
|
new = Column(Boolean)
|
||||||
|
|
||||||
author = relationship("User", primaryjoin="Submission.author_id==User.id")
|
author = relationship("User", primaryjoin="Submission.author_id==User.id")
|
||||||
oauth_app = relationship("OauthApp", viewonly=True)
|
oauth_app = relationship("OauthApp")
|
||||||
approved_by = relationship("User", uselist=False, primaryjoin="Submission.is_approved==User.id", viewonly=True)
|
approved_by = relationship("User", uselist=False, primaryjoin="Submission.is_approved==User.id")
|
||||||
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", viewonly=True)
|
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", back_populates="post")
|
||||||
flags = relationship("Flag", order_by="Flag.created_utc", viewonly=True)
|
flags = relationship("Flag", order_by="Flag.created_utc")
|
||||||
comments = relationship("Comment", primaryjoin="Comment.parent_submission==Submission.id")
|
comments = relationship("Comment", primaryjoin="Comment.parent_submission==Submission.id", back_populates="post")
|
||||||
subr = relationship("Sub", primaryjoin="foreign(Submission.sub)==remote(Sub.name)", viewonly=True)
|
subr = relationship("Sub", primaryjoin="foreign(Submission.sub)==remote(Sub.name)")
|
||||||
|
options = relationship("SubmissionOption", order_by="SubmissionOption.id")
|
||||||
|
|
||||||
bump_utc = deferred(Column(Integer, server_default=FetchedValue()))
|
bump_utc = deferred(Column(Integer, server_default=FetchedValue()))
|
||||||
|
|
||||||
|
@ -94,43 +96,6 @@ class Submission(Base):
|
||||||
if self.downvotes > 5 and 0.25 < self.upvotes / self.downvotes < 4: return True
|
if self.downvotes > 5 and 0.25 < self.upvotes / self.downvotes < 4: return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
|
||||||
@lazy
|
|
||||||
def options(self):
|
|
||||||
return g.db.query(Comment).filter_by(parent_submission = self.id, author_id = AUTOPOLLER_ID, level=1).order_by(Comment.id).all()
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
|
||||||
@lazy
|
|
||||||
def choices(self):
|
|
||||||
return g.db.query(Comment).filter_by(parent_submission = self.id, author_id = AUTOCHOICE_ID, level=1).order_by(Comment.id).all()
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
|
||||||
@lazy
|
|
||||||
def bet_options(self):
|
|
||||||
return g.db.query(Comment).filter_by(parent_submission = self.id, author_id = AUTOBETTER_ID, level=1).all()
|
|
||||||
|
|
||||||
@lazy
|
|
||||||
def total_poll_voted(self, v):
|
|
||||||
if v:
|
|
||||||
for option in self.options:
|
|
||||||
if option.poll_voted(v): return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@lazy
|
|
||||||
def total_choice_voted(self, v):
|
|
||||||
if v and self.choices:
|
|
||||||
return g.db.query(CommentVote).filter(CommentVote.user_id == v.id, CommentVote.comment_id.in_([x.id for x in self.choices])).first()
|
|
||||||
return None
|
|
||||||
|
|
||||||
@lazy
|
|
||||||
def total_bet_voted(self, v):
|
|
||||||
if "closed" in self.body.lower(): return True
|
|
||||||
if v:
|
|
||||||
for option in self.bet_options:
|
|
||||||
if option.poll_voted(v): return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
|
@ -401,44 +366,31 @@ class Submission(Base):
|
||||||
self.upvotes += amount
|
self.upvotes += amount
|
||||||
g.db.add(self)
|
g.db.add(self)
|
||||||
|
|
||||||
if not listing:
|
|
||||||
for c in self.options:
|
if self.options:
|
||||||
|
curr = [x for x in self.options if x.exclusive and x.voted(v)]
|
||||||
|
if curr: curr = " value=" + str(curr[0].id)
|
||||||
|
else: curr = ''
|
||||||
|
body += f'<input class="d-none" id="current-{self.id}"{curr}>'
|
||||||
|
|
||||||
|
for c in self.options:
|
||||||
|
if c.exclusive:
|
||||||
|
body += f'''<div class="custom-control"><input name="choice-{self.id}" autocomplete="off" class="custom-control-input" type="radio" id="{c.id}" onchange="choice_vote('{c.id}','{self.id}','post')"'''
|
||||||
|
if c.voted(v): body += " checked "
|
||||||
|
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html}<span class="presult-{self.id}'''
|
||||||
|
body += f'"> - <a href="/votes/post/option/{c.id}"><span id="choice-{c.id}">{c.upvotes}</span> votes</a></span></label></div>'
|
||||||
|
else:
|
||||||
body += f'<div class="custom-control"><input type="checkbox" class="custom-control-input" id="{c.id}" name="option"'
|
body += f'<div class="custom-control"><input type="checkbox" class="custom-control-input" id="{c.id}" name="option"'
|
||||||
if c.poll_voted(v): body += " checked"
|
if c.voted(v): body += " checked"
|
||||||
if v: body += f''' onchange="poll_vote('{c.id}', '{self.id}')"'''
|
if v: body += f''' onchange="poll_vote('{c.id}', 'post')"'''
|
||||||
else: body += f''' onchange="poll_vote_no_v('{c.id}', '{self.id}')"'''
|
else: body += f''' onchange="poll_vote_no_v('{c.id}', '{self.id}')"'''
|
||||||
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html}<span class="presult-{self.id}'''
|
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html}<span class="presult-{self.id}'''
|
||||||
if not self.total_poll_voted(v): body += ' d-none'
|
body += f'"> - <a href="/votes/post/option/{c.id}"><span id="poll-{c.id}">{c.upvotes}</span> votes</a></span></label></div>'
|
||||||
body += f'"> - <a href="/votes?link=t3_{c.id}"><span id="poll-{c.id}">{c.upvotes}</span> votes</a></span></label></div>'
|
|
||||||
|
|
||||||
if self.choices:
|
|
||||||
curr = self.total_choice_voted(v)
|
|
||||||
if curr: curr = " value=" + str(curr.comment_id)
|
|
||||||
else: curr = ''
|
|
||||||
body += f'<input class="d-none" id="current-{self.id}"{curr}>'
|
|
||||||
|
|
||||||
for c in self.choices:
|
|
||||||
body += f'''<div class="custom-control"><input name="choice-{self.id}" autocomplete="off" class="custom-control-input" type="radio" id="{c.id}" onchange="choice_vote('{c.id}','{self.id}')"'''
|
|
||||||
if c.poll_voted(v): body += " checked "
|
|
||||||
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html}<span class="presult-{self.id}'''
|
|
||||||
if not self.total_choice_voted(v): body += ' d-none'
|
|
||||||
body += f'"> - <a href="/votes?link=t3_{c.id}"><span id="choice-{c.id}">{c.upvotes}</span> votes</a></span></label></div>'
|
|
||||||
|
|
||||||
for c in self.bet_options:
|
|
||||||
body += f'''<div class="custom-control mt-3"><input autocomplete="off" class="custom-control-input bet" type="radio" id="{c.id}" onchange="bet_vote('{c.id}')"'''
|
|
||||||
if c.poll_voted(v): body += " checked "
|
|
||||||
if not (v and v.coins >= 200) or self.total_bet_voted(v) or not v.can_gamble: body += " disabled "
|
|
||||||
body += f'''><label class="custom-control-label" for="{c.id}">{c.body_html} - <a href="/votes?link=t3_{c.id}"><span id="bet-{c.id}">{c.upvotes}</span> bets</a>'''
|
|
||||||
if not self.total_bet_voted(v):
|
|
||||||
body += '''<span class="cost"> (cost of entry: 200 coins)</span>'''
|
|
||||||
body += "</label>"
|
|
||||||
if v and v.admin_level > 2:
|
|
||||||
body += f'''<button class="btn btn-primary px-2 mx-2" style="font-size:10px;padding:2px" onclick="post_toast(this,'/distribute/{c.id}')">Declare winner</button>'''
|
|
||||||
body += "</div>"
|
|
||||||
|
|
||||||
|
|
||||||
if self.author.sig_html and (self.author_id == MOOSE_ID or (not self.ghost and not (v and (v.sigs_disabled or v.poor)))):
|
|
||||||
body += f"<hr>{self.author.sig_html}"
|
if not listing and self.author.sig_html and (self.author_id == MOOSE_ID or (not self.ghost and not (v and (v.sigs_disabled or v.poor)))):
|
||||||
|
body += f"<hr>{self.author.sig_html}"
|
||||||
|
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Subscription(Base):
|
||||||
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
||||||
submission_id = Column(Integer, ForeignKey("submissions.id"), primary_key=True)
|
submission_id = Column(Integer, ForeignKey("submissions.id"), primary_key=True)
|
||||||
|
|
||||||
user = relationship("User", uselist=False, viewonly=True)
|
user = relationship("User", uselist=False)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
|
@ -135,16 +135,16 @@ class User(Base):
|
||||||
total_held_lottery_tickets = Column(Integer, default=0)
|
total_held_lottery_tickets = Column(Integer, default=0)
|
||||||
total_lottery_winnings = Column(Integer, default=0)
|
total_lottery_winnings = Column(Integer, default=0)
|
||||||
|
|
||||||
badges = relationship("Badge", order_by="Badge.created_utc", viewonly=True)
|
badges = relationship("Badge", order_by="Badge.created_utc", back_populates="user")
|
||||||
subscriptions = relationship("Subscription", viewonly=True)
|
subscriptions = relationship("Subscription", back_populates="user")
|
||||||
following = relationship("Follow", primaryjoin="Follow.user_id==User.id", viewonly=True)
|
following = relationship("Follow", primaryjoin="Follow.user_id==User.id", back_populates="user")
|
||||||
followers = relationship("Follow", primaryjoin="Follow.target_id==User.id", viewonly=True)
|
followers = relationship("Follow", primaryjoin="Follow.target_id==User.id", back_populates="target")
|
||||||
viewers = relationship("ViewerRelationship", primaryjoin="User.id == ViewerRelationship.user_id", viewonly=True)
|
viewers = relationship("ViewerRelationship", primaryjoin="User.id == ViewerRelationship.user_id")
|
||||||
blocking = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.user_id", viewonly=True)
|
blocking = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.user_id", back_populates="user")
|
||||||
blocked = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.target_id", viewonly=True)
|
blocked = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.target_id", back_populates="target")
|
||||||
authorizations = relationship("ClientAuth", viewonly=True)
|
authorizations = relationship("ClientAuth", back_populates="user")
|
||||||
awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", viewonly=True)
|
awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", back_populates="user")
|
||||||
referrals = relationship("User", viewonly=True)
|
referrals = relationship("User")
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|
||||||
|
@ -157,6 +157,10 @@ class User(Base):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<User(id={self.id})>"
|
||||||
|
|
||||||
|
|
||||||
@lazy
|
@lazy
|
||||||
def mods(self, sub):
|
def mods(self, sub):
|
||||||
return self.admin_level == 3 or bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
|
return self.admin_level == 3 or bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
|
||||||
|
|
|
@ -8,8 +8,8 @@ class UserBlock(Base):
|
||||||
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
||||||
target_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
target_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
|
||||||
|
|
||||||
user = relationship("User", primaryjoin="User.id==UserBlock.user_id", viewonly=True)
|
user = relationship("User", primaryjoin="User.id==UserBlock.user_id", back_populates="blocking")
|
||||||
target = relationship("User", primaryjoin="User.id==UserBlock.target_id", viewonly=True)
|
target = relationship("User", primaryjoin="User.id==UserBlock.target_id", back_populates="blocked")
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<UserBlock(user={self.user_id}, target={self.target_id})>"
|
return f"<UserBlock(user={self.user_id}, target={self.target_id})>"
|
|
@ -12,7 +12,7 @@ class ViewerRelationship(Base):
|
||||||
viewer_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
|
viewer_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
|
||||||
last_view_utc = Column(Integer)
|
last_view_utc = Column(Integer)
|
||||||
|
|
||||||
viewer = relationship("User", primaryjoin="ViewerRelationship.viewer_id == User.id", viewonly=True)
|
viewer = relationship("User", primaryjoin="ViewerRelationship.viewer_id == User.id")
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|
||||||
|
@ -21,6 +21,9 @@ class ViewerRelationship(Base):
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<ViewerRelationship(user_id={self.user_id}, viewer_id={self.viewer_id})>"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
def last_view_since(self):
|
def last_view_since(self):
|
||||||
|
|
|
@ -16,8 +16,8 @@ class Vote(Base):
|
||||||
real = Column(Boolean, default=True)
|
real = Column(Boolean, default=True)
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
|
||||||
user = relationship("User", lazy="subquery", viewonly=True)
|
user = relationship("User", lazy="subquery")
|
||||||
post = relationship("Submission", lazy="subquery", viewonly=True)
|
post = relationship("Submission", lazy="subquery")
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
@ -62,7 +62,7 @@ class CommentVote(Base):
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
|
||||||
user = relationship("User", lazy="subquery")
|
user = relationship("User", lazy="subquery")
|
||||||
comment = relationship("Comment", lazy="subquery", viewonly=True)
|
comment = relationship("Comment", lazy="subquery")
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||||
|
|
|
@ -155,9 +155,6 @@ AUTOJANNY_ID = 2
|
||||||
SNAPPY_ID = 3
|
SNAPPY_ID = 3
|
||||||
LONGPOSTBOT_ID = 4
|
LONGPOSTBOT_ID = 4
|
||||||
ZOZBOT_ID = 5
|
ZOZBOT_ID = 5
|
||||||
AUTOPOLLER_ID = 6
|
|
||||||
AUTOBETTER_ID = 7
|
|
||||||
AUTOCHOICE_ID = 8
|
|
||||||
BASEDBOT_ID = 0
|
BASEDBOT_ID = 0
|
||||||
|
|
||||||
SCHIZO_ID = 0
|
SCHIZO_ID = 0
|
||||||
|
@ -203,9 +200,6 @@ if SITE in {'rdrama.net', 'devrama.xyz'}:
|
||||||
SNAPPY_ID = 261
|
SNAPPY_ID = 261
|
||||||
LONGPOSTBOT_ID = 1832
|
LONGPOSTBOT_ID = 1832
|
||||||
ZOZBOT_ID = 1833
|
ZOZBOT_ID = 1833
|
||||||
AUTOPOLLER_ID = 6176
|
|
||||||
AUTOBETTER_ID = 7668
|
|
||||||
AUTOCHOICE_ID = 9167
|
|
||||||
|
|
||||||
SCHIZO_ID = 8494
|
SCHIZO_ID = 8494
|
||||||
A_ID = 1230
|
A_ID = 1230
|
||||||
|
@ -254,9 +248,6 @@ elif SITE == 'pcmemes.net':
|
||||||
SNAPPY_ID = 261
|
SNAPPY_ID = 261
|
||||||
LONGPOSTBOT_ID = 1832
|
LONGPOSTBOT_ID = 1832
|
||||||
ZOZBOT_ID = 1833
|
ZOZBOT_ID = 1833
|
||||||
AUTOPOLLER_ID = 2129
|
|
||||||
AUTOBETTER_ID = 1867
|
|
||||||
AUTOCHOICE_ID = 2072
|
|
||||||
BASEDBOT_ID = 800
|
BASEDBOT_ID = 800
|
||||||
|
|
||||||
KIPPY_ID = 1592
|
KIPPY_ID = 1592
|
||||||
|
@ -313,9 +304,7 @@ elif SITE == 'lgbdropthet.com':
|
||||||
else: # localhost or testing environment implied
|
else: # localhost or testing environment implied
|
||||||
pass
|
pass
|
||||||
|
|
||||||
poll_bots = AUTOPOLLER_ID, AUTOBETTER_ID, AUTOCHOICE_ID
|
bots = {NOTIFICATIONS_ID, AUTOJANNY_ID, SNAPPY_ID, LONGPOSTBOT_ID, ZOZBOT_ID, BASEDBOT_ID}
|
||||||
|
|
||||||
bots = {NOTIFICATIONS_ID, AUTOJANNY_ID, SNAPPY_ID, LONGPOSTBOT_ID, ZOZBOT_ID, BASEDBOT_ID}.union(poll_bots)
|
|
||||||
|
|
||||||
IMGUR_KEY = environ.get("IMGUR_KEY").strip()
|
IMGUR_KEY = environ.get("IMGUR_KEY").strip()
|
||||||
PUSHER_ID = environ.get("PUSHER_ID", "").strip()
|
PUSHER_ID = environ.get("PUSHER_ID", "").strip()
|
||||||
|
|
|
@ -144,7 +144,13 @@ def get_post(i, v=None, graceful=False, rendered=False):
|
||||||
)
|
)
|
||||||
|
|
||||||
if rendered:
|
if rendered:
|
||||||
posts = post.options(joinedload(Submission.flags), joinedload(Submission.awards), joinedload(Submission.author))
|
posts = post.options(
|
||||||
|
joinedload(Submission.flags),
|
||||||
|
joinedload(Submission.awards),
|
||||||
|
joinedload(Submission.author),
|
||||||
|
joinedload(Submission.options),
|
||||||
|
joinedload(Submission.options, SubmissionOption.votes)
|
||||||
|
)
|
||||||
|
|
||||||
post=post.one_or_none()
|
post=post.one_or_none()
|
||||||
|
|
||||||
|
@ -196,7 +202,12 @@ def get_posts(pids, v=None):
|
||||||
blocked,
|
blocked,
|
||||||
blocked.c.user_id == Submission.author_id,
|
blocked.c.user_id == Submission.author_id,
|
||||||
isouter=True
|
isouter=True
|
||||||
).options(joinedload(Submission.flags), joinedload(Submission.awards), joinedload(Submission.author)).all()
|
).options(joinedload(Submission.flags),
|
||||||
|
joinedload(Submission.awards),
|
||||||
|
joinedload(Submission.author),
|
||||||
|
joinedload(Submission.options),
|
||||||
|
joinedload(Submission.options, SubmissionOption.votes)
|
||||||
|
).all()
|
||||||
|
|
||||||
output = [p[0] for p in query]
|
output = [p[0] for p in query]
|
||||||
for i in range(len(output)):
|
for i in range(len(output)):
|
||||||
|
|
|
@ -16,4 +16,5 @@ from .feeds import *
|
||||||
from .awards import *
|
from .awards import *
|
||||||
from .giphy import *
|
from .giphy import *
|
||||||
from .subs import *
|
from .subs import *
|
||||||
from .lottery import *
|
from .lottery import *
|
||||||
|
from .polls import *
|
|
@ -101,8 +101,7 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
|
||||||
comments = comments.join(User, User.id == Comment.author_id).filter(User.shadowbanned == None)
|
comments = comments.join(User, User.id == Comment.author_id).filter(User.shadowbanned == None)
|
||||||
|
|
||||||
comments=comments.filter(
|
comments=comments.filter(
|
||||||
Comment.top_comment_id == c.top_comment_id,
|
Comment.top_comment_id == c.top_comment_id
|
||||||
Comment.author_id.notin_(poll_bots)
|
|
||||||
).join(
|
).join(
|
||||||
votes,
|
votes,
|
||||||
votes.c.comment_id == Comment.id,
|
votes.c.comment_id == Comment.id,
|
||||||
|
@ -365,30 +364,20 @@ def api_comment(v):
|
||||||
else: c.top_comment_id = parent.top_comment_id
|
else: c.top_comment_id = parent.top_comment_id
|
||||||
|
|
||||||
for option in options:
|
for option in options:
|
||||||
c_option = Comment(author_id=AUTOPOLLER_ID,
|
option = CommentOption(
|
||||||
parent_submission=parent_submission,
|
comment_id=c.id,
|
||||||
parent_comment_id=c.id,
|
|
||||||
level=level+1,
|
|
||||||
body_html=filter_emojis_only(option),
|
body_html=filter_emojis_only(option),
|
||||||
upvotes=0,
|
exclusive=False
|
||||||
is_bot=True,
|
)
|
||||||
ghost=c.ghost
|
g.db.add(option)
|
||||||
)
|
|
||||||
|
|
||||||
g.db.add(c_option)
|
|
||||||
|
|
||||||
for choice in choices:
|
for choice in choices:
|
||||||
c_choice = Comment(author_id=AUTOCHOICE_ID,
|
choice = CommentOption(
|
||||||
parent_submission=parent_submission,
|
comment_id=c.id,
|
||||||
parent_comment_id=c.id,
|
|
||||||
level=level+1,
|
|
||||||
body_html=filter_emojis_only(choice),
|
body_html=filter_emojis_only(choice),
|
||||||
upvotes=0,
|
exclusive=True
|
||||||
is_bot=True,
|
)
|
||||||
ghost=c.ghost
|
g.db.add(choice)
|
||||||
)
|
|
||||||
|
|
||||||
g.db.add(c_choice)
|
|
||||||
|
|
||||||
if request.host == 'pcmemes.net' and c.body.lower().startswith("based"):
|
if request.host == 'pcmemes.net' and c.body.lower().startswith("based"):
|
||||||
pill = based_regex.match(body)
|
pill = based_regex.match(body)
|
||||||
|
@ -664,29 +653,21 @@ def edit_comment(cid, v):
|
||||||
|
|
||||||
for i in poll_regex.finditer(body):
|
for i in poll_regex.finditer(body):
|
||||||
body = body.replace(i.group(0), "")
|
body = body.replace(i.group(0), "")
|
||||||
c_option = Comment(author_id=AUTOPOLLER_ID,
|
option = CommentOption(
|
||||||
parent_submission=c.parent_submission,
|
comment_id=c.id,
|
||||||
parent_comment_id=c.id,
|
|
||||||
level=c.level+1,
|
|
||||||
body_html=filter_emojis_only(i.group(1)),
|
body_html=filter_emojis_only(i.group(1)),
|
||||||
upvotes=0,
|
exclusive = False
|
||||||
is_bot=True,
|
)
|
||||||
ghost=c.ghost
|
g.db.add(option)
|
||||||
)
|
|
||||||
g.db.add(c_option)
|
|
||||||
|
|
||||||
for i in choice_regex.finditer(body):
|
for i in choice_regex.finditer(body):
|
||||||
body = body.replace(i.group(0), "")
|
body = body.replace(i.group(0), "")
|
||||||
c_choice = Comment(author_id=AUTOCHOICE_ID,
|
option = CommentOption(
|
||||||
parent_submission=c.parent_submission,
|
comment_id=c.id,
|
||||||
parent_comment_id=c.id,
|
|
||||||
level=c.level+1,
|
|
||||||
body_html=filter_emojis_only(i.group(1)),
|
body_html=filter_emojis_only(i.group(1)),
|
||||||
upvotes=0,
|
exclusive = True
|
||||||
is_bot=True,
|
)
|
||||||
ghost=c.ghost
|
g.db.add(option)
|
||||||
)
|
|
||||||
g.db.add(c_choice)
|
|
||||||
|
|
||||||
if '!slots' not in body.lower() and '!blackjack' not in body.lower() and '!wordle' not in body.lower() and AGENDAPOSTER_PHRASE not in body.lower():
|
if '!slots' not in body.lower() and '!blackjack' not in body.lower() and '!wordle' not in body.lower() and AGENDAPOSTER_PHRASE not in body.lower():
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
|
|
|
@ -463,9 +463,7 @@ def all_comments(v):
|
||||||
@cache.memoize(timeout=86400)
|
@cache.memoize(timeout=86400)
|
||||||
def comment_idlist(page=1, v=None, nsfw=False, sort="new", t="all", gt=0, lt=0, site=None):
|
def comment_idlist(page=1, v=None, nsfw=False, sort="new", t="all", gt=0, lt=0, site=None):
|
||||||
|
|
||||||
excluded = v.userblocks + [AUTOPOLLER_ID, AUTOBETTER_ID, AUTOCHOICE_ID]
|
comments = g.db.query(Comment.id).filter(Comment.parent_submission != None, Comment.author_id.notin_(v.userblocks))
|
||||||
|
|
||||||
comments = g.db.query(Comment.id).filter(Comment.parent_submission != None, Comment.author_id.notin_(excluded))
|
|
||||||
|
|
||||||
if v.admin_level < 2:
|
if v.admin_level < 2:
|
||||||
private = [x[0] for x in g.db.query(Submission.id).filter(Submission.private == True).all()]
|
private = [x[0] for x in g.db.query(Submission.id).filter(Submission.private == True).all()]
|
||||||
|
|
|
@ -313,7 +313,7 @@ def sign_up_post(v):
|
||||||
ref_id = int(request.values.get("referred_by", 0))
|
ref_id = int(request.values.get("referred_by", 0))
|
||||||
|
|
||||||
users_count = g.db.query(User).count()
|
users_count = g.db.query(User).count()
|
||||||
if users_count == 8:
|
if users_count == 5:
|
||||||
admin_level=3
|
admin_level=3
|
||||||
session["history"] = []
|
session["history"] = []
|
||||||
else: admin_level=0
|
else: admin_level=0
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
from files.helpers.wrappers import *
|
||||||
|
from files.helpers.get import *
|
||||||
|
from files.helpers.const import *
|
||||||
|
from files.classes import *
|
||||||
|
from flask import *
|
||||||
|
from files.__main__ import app
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/vote/post/option/<option_id>")
|
||||||
|
@is_not_permabanned
|
||||||
|
def api_vote_option(option_id, v):
|
||||||
|
|
||||||
|
option_id = int(option_id)
|
||||||
|
|
||||||
|
option = g.db.get(SubmissionOption, option_id)
|
||||||
|
|
||||||
|
if not option: abort(404)
|
||||||
|
|
||||||
|
if option.exclusive:
|
||||||
|
vote = g.db.query(SubmissionOptionVote).join(SubmissionOption).filter(
|
||||||
|
SubmissionOptionVote.user_id==v.id,
|
||||||
|
SubmissionOptionVote.submission_id==option.submission_id,
|
||||||
|
SubmissionOption.exclusive==True).one_or_none()
|
||||||
|
if vote:
|
||||||
|
g.db.delete(vote)
|
||||||
|
|
||||||
|
existing = g.db.query(SubmissionOptionVote).filter_by(option_id=option_id, user_id=v.id).one_or_none()
|
||||||
|
if not existing:
|
||||||
|
vote = SubmissionOptionVote(
|
||||||
|
option_id=option_id,
|
||||||
|
user_id=v.id,
|
||||||
|
submission_id=option.submission_id,
|
||||||
|
)
|
||||||
|
g.db.add(vote)
|
||||||
|
elif existing:
|
||||||
|
g.db.delete(existing)
|
||||||
|
|
||||||
|
return "", 204
|
||||||
|
|
||||||
|
@app.get("/votes/post/option/<option_id>")
|
||||||
|
@auth_required
|
||||||
|
def option_votes(option_id, v):
|
||||||
|
|
||||||
|
option_id = int(option_id)
|
||||||
|
|
||||||
|
option = g.db.get(SubmissionOption, option_id)
|
||||||
|
|
||||||
|
if not option: abort(404)
|
||||||
|
|
||||||
|
ups = g.db.query(SubmissionOptionVote).filter_by(option_id=option_id).options(
|
||||||
|
joinedload(SubmissionOptionVote.user)
|
||||||
|
).all()
|
||||||
|
|
||||||
|
return render_template("poll_votes.html",
|
||||||
|
v=v,
|
||||||
|
thing=option,
|
||||||
|
ups=ups)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/vote/comment/option/<option_id>")
|
||||||
|
@is_not_permabanned
|
||||||
|
def api_vote_option_comment(option_id, v):
|
||||||
|
|
||||||
|
option_id = int(option_id)
|
||||||
|
|
||||||
|
option = g.db.get(CommentOption, option_id)
|
||||||
|
|
||||||
|
if not option: abort(404)
|
||||||
|
|
||||||
|
if option.exclusive:
|
||||||
|
vote = g.db.query(CommentOptionVote).join(CommentOption).filter(
|
||||||
|
CommentOptionVote.user_id==v.id,
|
||||||
|
CommentOptionVote.comment_id==option.comment_id,
|
||||||
|
CommentOption.exclusive==True).one_or_none()
|
||||||
|
if vote:
|
||||||
|
g.db.delete(vote)
|
||||||
|
|
||||||
|
existing = g.db.query(CommentOptionVote).filter_by(option_id=option_id, user_id=v.id).one_or_none()
|
||||||
|
if not existing:
|
||||||
|
vote = CommentOptionVote(
|
||||||
|
option_id=option_id,
|
||||||
|
user_id=v.id,
|
||||||
|
comment_id=option.comment_id,
|
||||||
|
)
|
||||||
|
g.db.add(vote)
|
||||||
|
elif existing:
|
||||||
|
g.db.delete(existing)
|
||||||
|
|
||||||
|
return "", 204
|
||||||
|
|
||||||
|
@app.get("/votes/comment/option/<option_id>")
|
||||||
|
@auth_required
|
||||||
|
def option_votes_comment(option_id, v):
|
||||||
|
|
||||||
|
option_id = int(option_id)
|
||||||
|
|
||||||
|
option = g.db.get(CommentOption, option_id)
|
||||||
|
|
||||||
|
if not option: abort(404)
|
||||||
|
|
||||||
|
ups = g.db.query(CommentOptionVote).filter_by(option_id=option_id).options(
|
||||||
|
joinedload(CommentOptionVote.user)
|
||||||
|
).all()
|
||||||
|
|
||||||
|
return render_template("poll_votes.html",
|
||||||
|
v=v,
|
||||||
|
thing=option,
|
||||||
|
ups=ups)
|
|
@ -158,7 +158,7 @@ def post_id(pid, anything=None, v=None, sub=None):
|
||||||
if not (v and v.shadowbanned) and not (v and v.admin_level >= 2):
|
if not (v and v.shadowbanned) and not (v and v.admin_level >= 2):
|
||||||
comments = comments.join(User, User.id == Comment.author_id).filter(User.shadowbanned == None)
|
comments = comments.join(User, User.id == Comment.author_id).filter(User.shadowbanned == None)
|
||||||
|
|
||||||
comments=comments.filter(Comment.parent_submission == post.id, Comment.author_id.notin_(poll_bots)).join(
|
comments=comments.filter(Comment.parent_submission == post.id).join(
|
||||||
votes,
|
votes,
|
||||||
votes.c.comment_id == Comment.id,
|
votes.c.comment_id == Comment.id,
|
||||||
isouter=True
|
isouter=True
|
||||||
|
@ -170,7 +170,13 @@ def post_id(pid, anything=None, v=None, sub=None):
|
||||||
blocked,
|
blocked,
|
||||||
blocked.c.user_id == Comment.author_id,
|
blocked.c.user_id == Comment.author_id,
|
||||||
isouter=True
|
isouter=True
|
||||||
).options(joinedload(Comment.flags), joinedload(Comment.awards), joinedload(Comment.author))
|
).options(
|
||||||
|
joinedload(Comment.flags),
|
||||||
|
joinedload(Comment.awards),
|
||||||
|
joinedload(Comment.author),
|
||||||
|
joinedload(Comment.options),
|
||||||
|
joinedload(Comment.options, CommentOption.votes)
|
||||||
|
)
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
for c in comments.all():
|
for c in comments.all():
|
||||||
|
@ -192,7 +198,7 @@ def post_id(pid, anything=None, v=None, sub=None):
|
||||||
else:
|
else:
|
||||||
pinned = g.db.query(Comment).filter(Comment.parent_submission == post.id, Comment.stickied != None).all()
|
pinned = g.db.query(Comment).filter(Comment.parent_submission == post.id, Comment.stickied != None).all()
|
||||||
|
|
||||||
comments = g.db.query(Comment).join(User, User.id == Comment.author_id).filter(User.shadowbanned == None, Comment.parent_submission == post.id, Comment.author_id.notin_(poll_bots), Comment.level == 1, Comment.stickied == None)
|
comments = g.db.query(Comment).join(User, User.id == Comment.author_id).filter(User.shadowbanned == None, Comment.parent_submission == post.id, Comment.level == 1, Comment.stickied == None)
|
||||||
|
|
||||||
comments = sort_comments(sort, comments)
|
comments = sort_comments(sort, comments)
|
||||||
|
|
||||||
|
@ -268,7 +274,7 @@ def viewmore(v, pid, sort, offset):
|
||||||
votes.c.vote_type,
|
votes.c.vote_type,
|
||||||
blocking.c.target_id,
|
blocking.c.target_id,
|
||||||
blocked.c.target_id,
|
blocked.c.target_id,
|
||||||
).filter(Comment.parent_submission == pid, Comment.author_id.notin_(poll_bots), Comment.stickied == None, Comment.id.notin_(ids))
|
).filter(Comment.parent_submission == pid, Comment.stickied == None, Comment.id.notin_(ids))
|
||||||
|
|
||||||
if not (v and v.shadowbanned) and not (v and v.admin_level >= 2):
|
if not (v and v.shadowbanned) and not (v and v.admin_level >= 2):
|
||||||
comments = comments.join(User, User.id == Comment.author_id).filter(User.shadowbanned == None)
|
comments = comments.join(User, User.id == Comment.author_id).filter(User.shadowbanned == None)
|
||||||
|
@ -303,7 +309,7 @@ def viewmore(v, pid, sort, offset):
|
||||||
second = [c[0] for c in comments.filter(or_(Comment.slots_result != None, Comment.blackjack_result != None, Comment.wordle_result != None), func.length(Comment.body_html) <= 100).all()]
|
second = [c[0] for c in comments.filter(or_(Comment.slots_result != None, Comment.blackjack_result != None, Comment.wordle_result != None), func.length(Comment.body_html) <= 100).all()]
|
||||||
comments = first + second
|
comments = first + second
|
||||||
else:
|
else:
|
||||||
comments = g.db.query(Comment).join(User, User.id == Comment.author_id).filter(User.shadowbanned == None, Comment.parent_submission == pid, Comment.author_id.notin_(poll_bots), Comment.level == 1, Comment.stickied == None, Comment.id.notin_(ids))
|
comments = g.db.query(Comment).join(User, User.id == Comment.author_id).filter(User.shadowbanned == None, Comment.parent_submission == pid, Comment.level == 1, Comment.stickied == None, Comment.id.notin_(ids))
|
||||||
|
|
||||||
comments = sort_comments(sort, comments)
|
comments = sort_comments(sort, comments)
|
||||||
|
|
||||||
|
@ -427,27 +433,22 @@ def edit_post(pid, v):
|
||||||
|
|
||||||
for i in poll_regex.finditer(body):
|
for i in poll_regex.finditer(body):
|
||||||
body = body.replace(i.group(0), "")
|
body = body.replace(i.group(0), "")
|
||||||
c = Comment(author_id=AUTOPOLLER_ID,
|
option = SubmissionOption(
|
||||||
parent_submission=p.id,
|
submission_id=p.id,
|
||||||
level=1,
|
|
||||||
body_html=filter_emojis_only(i.group(1)),
|
body_html=filter_emojis_only(i.group(1)),
|
||||||
upvotes=0,
|
exclusive = False
|
||||||
is_bot=True,
|
)
|
||||||
ghost=p.ghost
|
g.db.add(option)
|
||||||
)
|
|
||||||
g.db.add(c)
|
|
||||||
|
|
||||||
for i in choice_regex.finditer(body):
|
for i in choice_regex.finditer(body):
|
||||||
body = body.replace(i.group(0), "")
|
body = body.replace(i.group(0), "")
|
||||||
c = Comment(author_id=AUTOCHOICE_ID,
|
option = SubmissionOption(
|
||||||
parent_submission=p.id,
|
submission_id=p.id,
|
||||||
level=1,
|
|
||||||
body_html=filter_emojis_only(i.group(1)),
|
body_html=filter_emojis_only(i.group(1)),
|
||||||
upvotes=0,
|
exclusive = True
|
||||||
is_bot=True,
|
)
|
||||||
ghost=p.ghost
|
g.db.add(option)
|
||||||
)
|
|
||||||
g.db.add(c)
|
|
||||||
|
|
||||||
body_html = sanitize(body, edit=True)
|
body_html = sanitize(body, edit=True)
|
||||||
|
|
||||||
|
@ -974,26 +975,20 @@ def submit_post(v, sub=None):
|
||||||
g.db.add(bet_option)
|
g.db.add(bet_option)
|
||||||
|
|
||||||
for option in options:
|
for option in options:
|
||||||
c = Comment(author_id=AUTOPOLLER_ID,
|
option = SubmissionOption(
|
||||||
parent_submission=post.id,
|
submission_id=post.id,
|
||||||
level=1,
|
|
||||||
body_html=filter_emojis_only(option),
|
body_html=filter_emojis_only(option),
|
||||||
upvotes=0,
|
exclusive=False
|
||||||
is_bot=True,
|
)
|
||||||
ghost=post.ghost
|
g.db.add(option)
|
||||||
)
|
|
||||||
g.db.add(c)
|
|
||||||
|
|
||||||
for choice in choices:
|
for choice in choices:
|
||||||
c = Comment(author_id=AUTOCHOICE_ID,
|
choice = SubmissionOption(
|
||||||
parent_submission=post.id,
|
submission_id=post.id,
|
||||||
level=1,
|
|
||||||
body_html=filter_emojis_only(choice),
|
body_html=filter_emojis_only(choice),
|
||||||
upvotes=0,
|
exclusive=True
|
||||||
is_bot=True,
|
)
|
||||||
ghost=post.ghost
|
g.db.add(choice)
|
||||||
)
|
|
||||||
g.db.add(c)
|
|
||||||
|
|
||||||
vote = Vote(user_id=v.id,
|
vote = Vote(user_id=v.id,
|
||||||
vote_type=1,
|
vote_type=1,
|
||||||
|
|
|
@ -317,7 +317,7 @@ def upvoting(v, username):
|
||||||
|
|
||||||
votes = g.db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote, Vote.submission_id==Submission.id).filter(Submission.ghost == False, Submission.is_banned == False, Submission.deleted_utc == 0, Vote.vote_type==1, Vote.user_id==id).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).all()
|
votes = g.db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote, Vote.submission_id==Submission.id).filter(Submission.ghost == False, Submission.is_banned == False, Submission.deleted_utc == 0, Vote.vote_type==1, Vote.user_id==id).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).all()
|
||||||
|
|
||||||
votes2 = g.db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote, CommentVote.comment_id==Comment.id).filter(Comment.ghost == False, Comment.is_banned == False, Comment.deleted_utc == 0, CommentVote.vote_type==1, CommentVote.user_id==id, Comment.author_id.notin_(poll_bots)).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).all()
|
votes2 = g.db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote, CommentVote.comment_id==Comment.id).filter(Comment.ghost == False, Comment.is_banned == False, Comment.deleted_utc == 0, CommentVote.vote_type==1, CommentVote.user_id==id).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).all()
|
||||||
|
|
||||||
votes = Counter(dict(votes)) + Counter(dict(votes2))
|
votes = Counter(dict(votes)) + Counter(dict(votes2))
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,9 @@ from flask import *
|
||||||
from files.__main__ import app, limiter, cache
|
from files.__main__ import app, limiter, cache
|
||||||
from os import environ
|
from os import environ
|
||||||
|
|
||||||
@app.get("/votes")
|
@app.get("/votes/<linK>")
|
||||||
@auth_required
|
@auth_required
|
||||||
def admin_vote_info_get(v):
|
def vote_info_get(v, link):
|
||||||
link = request.values.get("link")
|
|
||||||
if not link: return render_template("votes.html", v=v)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if "t2_" in link: thing = get_post(int(link.split("t2_")[1]), v=v)
|
if "t2_" in link: thing = get_post(int(link.split("t2_")[1]), v=v)
|
||||||
elif "t3_" in link: thing = get_comment(int(link.split("t3_")[1]), v=v)
|
elif "t3_" in link: thing = get_comment(int(link.split("t3_")[1]), v=v)
|
||||||
|
@ -20,8 +17,6 @@ def admin_vote_info_get(v):
|
||||||
|
|
||||||
if thing.ghost and v.id != AEVANN_ID: abort(403)
|
if thing.ghost and v.id != AEVANN_ID: abort(403)
|
||||||
|
|
||||||
if not thing.author:
|
|
||||||
print(thing.id, flush=True)
|
|
||||||
if isinstance(thing, Submission):
|
if isinstance(thing, Submission):
|
||||||
if thing.author.shadowbanned and not (v and v.admin_level):
|
if thing.author.shadowbanned and not (v and v.admin_level):
|
||||||
thing_id = g.db.query(Submission.id).filter_by(upvotes=thing.upvotes, downvotes=thing.downvotes).order_by(Submission.id).first()[0]
|
thing_id = g.db.query(Submission.id).filter_by(upvotes=thing.upvotes, downvotes=thing.downvotes).order_by(Submission.id).first()[0]
|
||||||
|
@ -151,8 +146,6 @@ def api_vote_comment(comment_id, new, v):
|
||||||
except: abort(404)
|
except: abort(404)
|
||||||
|
|
||||||
comment = get_comment(comment_id)
|
comment = get_comment(comment_id)
|
||||||
|
|
||||||
if new == 1 and comment.author_id in poll_bots: return {"error": "forbidden."}, 403
|
|
||||||
|
|
||||||
existing = g.db.query(CommentVote).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
|
existing = g.db.query(CommentVote).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
|
||||||
|
|
||||||
|
@ -207,100 +200,4 @@ def api_vote_comment(comment_id, new, v):
|
||||||
comment.realupvotes = g.db.query(CommentVote).filter_by(comment_id=comment.id, real=True).count()
|
comment.realupvotes = g.db.query(CommentVote).filter_by(comment_id=comment.id, real=True).count()
|
||||||
if comment.author.progressivestack: comment.realupvotes *= 2
|
if comment.author.progressivestack: comment.realupvotes *= 2
|
||||||
g.db.add(comment)
|
g.db.add(comment)
|
||||||
return "", 204
|
return "", 204
|
||||||
|
|
||||||
|
|
||||||
@app.post("/vote/poll/<comment_id>")
|
|
||||||
@is_not_permabanned
|
|
||||||
def api_vote_poll(comment_id, v):
|
|
||||||
|
|
||||||
vote = request.values.get("vote")
|
|
||||||
if vote == "true": new = 1
|
|
||||||
elif vote == "false": new = 0
|
|
||||||
else: abort(400)
|
|
||||||
|
|
||||||
comment_id = int(comment_id)
|
|
||||||
comment = get_comment(comment_id)
|
|
||||||
|
|
||||||
existing = g.db.query(CommentVote).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
|
|
||||||
|
|
||||||
if existing and existing.vote_type == new: return "", 204
|
|
||||||
|
|
||||||
if existing:
|
|
||||||
if new == 1:
|
|
||||||
existing.vote_type = new
|
|
||||||
g.db.add(existing)
|
|
||||||
else: g.db.delete(existing)
|
|
||||||
elif new == 1:
|
|
||||||
vote = CommentVote(user_id=v.id, vote_type=new, comment_id=comment.id)
|
|
||||||
g.db.add(vote)
|
|
||||||
|
|
||||||
g.db.flush()
|
|
||||||
comment.upvotes = g.db.query(CommentVote).filter_by(comment_id=comment.id, vote_type=1).count()
|
|
||||||
g.db.add(comment)
|
|
||||||
return "", 204
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/bet/<comment_id>")
|
|
||||||
@limiter.limit("1/second;30/minute;200/hour;1000/day")
|
|
||||||
@limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{request.host}-{session.get("lo_user")}')
|
|
||||||
@is_not_permabanned
|
|
||||||
def bet(comment_id, v):
|
|
||||||
if not v.can_gamble: return {"error": "You have gambling disabled!"}
|
|
||||||
|
|
||||||
if v.coins < 200: return {"error": "You don't have 200 coins!"}
|
|
||||||
|
|
||||||
vote = request.values.get("vote")
|
|
||||||
comment_id = int(comment_id)
|
|
||||||
comment = get_comment(comment_id)
|
|
||||||
|
|
||||||
option_ids = map(lambda x: x.id, comment.post.bet_options)
|
|
||||||
existing = g.db.query(CommentVote).filter_by(user_id=v.id) \
|
|
||||||
.filter(CommentVote.comment_id.in_(option_ids)).one_or_none()
|
|
||||||
if existing: return "", 204
|
|
||||||
|
|
||||||
vote = CommentVote(user_id=v.id, vote_type=1, comment_id=comment.id)
|
|
||||||
g.db.add(vote)
|
|
||||||
|
|
||||||
comment.upvotes += 1
|
|
||||||
g.db.add(comment)
|
|
||||||
|
|
||||||
v.coins -= 200
|
|
||||||
g.db.add(v)
|
|
||||||
autobetter = get_account(AUTOBETTER_ID)
|
|
||||||
autobetter.coins += 200
|
|
||||||
g.db.add(autobetter)
|
|
||||||
|
|
||||||
return "", 204
|
|
||||||
|
|
||||||
@app.post("/vote/choice/<comment_id>")
|
|
||||||
@is_not_permabanned
|
|
||||||
def api_vote_choice(comment_id, v):
|
|
||||||
|
|
||||||
comment_id = int(comment_id)
|
|
||||||
comment = get_comment(comment_id)
|
|
||||||
|
|
||||||
existing = g.db.query(CommentVote).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
|
|
||||||
|
|
||||||
if existing and existing.vote_type == 1: return "", 204
|
|
||||||
|
|
||||||
if existing:
|
|
||||||
existing.vote_type = 1
|
|
||||||
g.db.add(existing)
|
|
||||||
else:
|
|
||||||
vote = CommentVote(user_id=v.id, vote_type=1, comment_id=comment.id)
|
|
||||||
g.db.add(vote)
|
|
||||||
|
|
||||||
if comment.parent_comment: parent = comment.parent_comment
|
|
||||||
else: parent = comment.post
|
|
||||||
|
|
||||||
vote = parent.total_choice_voted(v)
|
|
||||||
if vote:
|
|
||||||
vote.comment.upvotes = g.db.query(CommentVote).filter_by(comment_id=vote.comment.id, vote_type=1).count() - 1
|
|
||||||
g.db.add(vote.comment)
|
|
||||||
g.db.delete(vote)
|
|
||||||
|
|
||||||
g.db.flush()
|
|
||||||
comment.upvotes = g.db.query(CommentVote).filter_by(comment_id=comment.id, vote_type=1).count()
|
|
||||||
g.db.add(comment)
|
|
||||||
return "", 204
|
|
|
@ -443,7 +443,7 @@
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if not c.ghost or v.id == AEVANN_ID %}<a href="/votes?link={{c.fullname}}" class="btn caction nobackground px-1 text-muted"><i class="fas fa-arrows-v"></i>Votes</a>{% endif %}
|
{% if not c.ghost or v.id == AEVANN_ID %}<a href="/votes/{{c.fullname}}" class="btn caction nobackground px-1 text-muted"><i class="fas fa-arrows-v"></i>Votes</a>{% endif %}
|
||||||
|
|
||||||
<a class="btn caction nobackground px-1 text-muted" href="{{c.permalink}}"><i class="fas fa-book-open"></i>Context</a>
|
<a class="btn caction nobackground px-1 text-muted" href="{{c.permalink}}"><i class="fas fa-book-open"></i>Context</a>
|
||||||
|
|
||||||
|
@ -646,7 +646,7 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<ul class="list-group comment-actions">
|
<ul class="list-group comment-actions">
|
||||||
|
|
||||||
{% if not c.ghost or v.id == AEVANN_ID %}<a href="/votes?link={{c.fullname}}"><li class="list-group-item"><i class="fas fa-arrows-v mr-2"></i>Votes</li></a>{% endif %}
|
{% if not c.ghost or v.id == AEVANN_ID %}<a href="/votes/{{c.fullname}}"><li class="list-group-item"><i class="fas fa-arrows-v mr-2"></i>Votes</li></a>{% endif %}
|
||||||
|
|
||||||
<a class="list-group-item" href="{{c.permalink}}"><i class="fas fa-book-open mr-2"></i>Context</a>
|
<a class="list-group-item" href="{{c.permalink}}"><i class="fas fa-book-open mr-2"></i>Context</a>
|
||||||
|
|
||||||
|
|
|
@ -142,11 +142,11 @@ Text 2
|
||||||
<td>
|
<td>
|
||||||
<div class="custom-control">
|
<div class="custom-control">
|
||||||
<input autocomplete="off" type="checkbox" class="custom-control-input" id="422741">
|
<input autocomplete="off" type="checkbox" class="custom-control-input" id="422741">
|
||||||
<label class="custom-control-label" for="422741">bussy - <a href="/votes?link=t3_422741"><span id="poll-422741">0</span> votes</a></label>
|
<label class="custom-control-label" for="422741">bussy - <a href="/votes/t3_422741"><span id="poll-422741">0</span> votes</a></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-control">
|
<div class="custom-control">
|
||||||
<input autocomplete="off" type="checkbox" class="custom-control-input" id="422742">
|
<input autocomplete="off" type="checkbox" class="custom-control-input" id="422742">
|
||||||
<label class="custom-control-label" for="422742">gussy - <a href="/votes?link=t3_422742"><span id="poll-422742">0</span> votes</a></label>
|
<label class="custom-control-label" for="422742">gussy - <a href="/votes/t3_422742"><span id="poll-422742">0</span> votes</a></label>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -161,11 +161,11 @@ Text 2
|
||||||
<td>
|
<td>
|
||||||
<div class="custom-control">
|
<div class="custom-control">
|
||||||
<input name="choice" autocomplete="off" type="radio" class="custom-control-input" id="1338113">
|
<input name="choice" autocomplete="off" type="radio" class="custom-control-input" id="1338113">
|
||||||
<label class="custom-control-label" for="1338113">bussy - <a href="/votes?link=t3_1338113"><span id="choice-1338113">0</span> votes</a></label>
|
<label class="custom-control-label" for="1338113">bussy - <a href="/votes/t3_1338113"><span id="choice-1338113">0</span> votes</a></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-control">
|
<div class="custom-control">
|
||||||
<input name="choice" autocomplete="off" type="radio" class="custom-control-input" id="1338114">
|
<input name="choice" autocomplete="off" type="radio" class="custom-control-input" id="1338114">
|
||||||
<label class="custom-control-label" for="1338114">gussy - <a href="/votes?link=t3_1338114"><span id="choice-1338114">0</span> votes</a></label>
|
<label class="custom-control-label" for="1338114">gussy - <a href="/votes/t3_1338114"><span id="choice-1338114">0</span> votes</a></label>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
{% extends "default.html" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
<title>{{SITE_NAME}}</title>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% if thing %}
|
||||||
|
|
||||||
|
<script src="/assets/js/sort_table.js?v=243"></script>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Votes: {{ups | length}}</h2>
|
||||||
|
<div class="overflow-x-auto mt-5">
|
||||||
|
<table class="table table-striped mb-5">
|
||||||
|
<thead class="bg-primary text-white">
|
||||||
|
<tr>
|
||||||
|
<th>User</th>
|
||||||
|
<th role="button" onclick="sort_table(1)">User Truescore</th>
|
||||||
|
<th>Vote Time</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
{% for vote in ups %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a style="color:#{{vote.user.namecolor}};font-weight:bold" href="/@{{vote.user.username}}">
|
||||||
|
<img loading="lazy" src="{{vote.user.profile_url}}" class="pp20">
|
||||||
|
<span {% if vote.user.patron %}class="patron" style="background-color:#{{vote.user.namecolor}}"{% endif %}>
|
||||||
|
{{vote.user.username}}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{vote.user.truecoins}}</td>
|
||||||
|
<td>{{vote.created_datetime}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -6,7 +6,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
{% if not p.ghost or v.id == AEVANN_ID %}<a class="list-inline-item" href="/votes?link={{p.fullname}}"><i class="fas fa-arrows-v"></i>Votes</a>{% endif %}
|
{% if not p.ghost or v.id == AEVANN_ID %}<a class="list-inline-item" href="/votes/{{p.fullname}}"><i class="fas fa-arrows-v"></i>Votes</a>{% endif %}
|
||||||
|
|
||||||
{% if v %}
|
{% if v %}
|
||||||
<a class="list-inline-item text-muted d-none d-md-inline-block" role="button" data-bs-toggle="modal" data-bs-target="#awardModal" data-url='/award/post/{{p.id}}'><i class="fas fa-gift fa-fw"></i>Give Award</a>
|
<a class="list-inline-item text-muted d-none d-md-inline-block" role="button" data-bs-toggle="modal" data-bs-target="#awardModal" data-url='/award/post/{{p.id}}'><i class="fas fa-gift fa-fw"></i>Give Award</a>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
{% if not p.ghost or v.id == AEVANN_ID %}<a class="btn-block" href="/votes?link={{p.fullname}}"><button class="nobackground btn btn-link btn-block btn-lg text-left text-muted"><i class="fas fa-arrows-v text-center text-muted mr-3"></i>Votes</button></a>{% endif %}
|
{% if not p.ghost or v.id == AEVANN_ID %}<a class="btn-block" href="/votes/{{p.fullname}}"><button class="nobackground btn btn-link btn-block btn-lg text-left text-muted"><i class="fas fa-arrows-v text-center text-muted mr-3"></i>Votes</button></a>{% endif %}
|
||||||
|
|
||||||
<button data-bs-dismiss="modal" class="copy-link nobackground btn btn-link btn-block btn-lg text-left text-muted" data-clipboard-text="{% if request.host == 'rdrama.net' %}https://chapotraphouse.club{{p.shortlink}}{% else %}{{p.permalink}}{% endif %}"><i class="far fa-copy text-center text-muted mr-3"></i>Copy link</button>
|
<button data-bs-dismiss="modal" class="copy-link nobackground btn btn-link btn-block btn-lg text-left text-muted" data-clipboard-text="{% if request.host == 'rdrama.net' %}https://chapotraphouse.club{{p.shortlink}}{% else %}{{p.permalink}}{% endif %}"><i class="far fa-copy text-center text-muted mr-3"></i>Copy link</button>
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ set CACHE_VER = {
|
||||||
|
|
||||||
'js/award_modal.js': 253,
|
'js/award_modal.js': 253,
|
||||||
'js/bootstrap.js': 272,
|
'js/bootstrap.js': 272,
|
||||||
'js/comments+submission_listing.js': 261,
|
'js/comments+submission_listing.js': 262,
|
||||||
'js/submission_listing.js': 261,
|
'js/submission_listing.js': 261,
|
||||||
'js/emoji_modal.js': 297,
|
'js/emoji_modal.js': 297,
|
||||||
'js/formatting.js': 240,
|
'js/formatting.js': 240,
|
||||||
|
|
14
seed-db.sql
14
seed-db.sql
|
@ -21,19 +21,7 @@ INSERT INTO public.users (username, passhash, created_utc, admin_level, over_18,
|
||||||
('zozbot', '', extract(epoch from now()), 0, true, true, '', '', 0, false,
|
('zozbot', '', extract(epoch from now()), 0, true, true, '', '', 0, false,
|
||||||
0, 'zozbot', '', 'hot', 'top', 'day', '62ca56', 'e4432d',
|
0, 'zozbot', '', 'hot', 'top', 'day', '62ca56', 'e4432d',
|
||||||
'', 'dark', '30409f', false, 'old.reddit.com', '', '', 0, 0,
|
'', 'dark', '30409f', false, 'old.reddit.com', '', '', 0, 0,
|
||||||
0, 0, '', 'Verified', 0, false, '/i/pfps/5.webp', '/i/pfps/5.webp'),
|
0, 0, '', 'Verified', 0, false, '/i/pfps/5.webp', '/i/pfps/5.webp');
|
||||||
('AutoPoller', '', extract(epoch from now()), 0, true, true, '', '', 0, false,
|
|
||||||
0, 'AutoPoller', '', 'hot', 'top', 'day', '62ca56', 'e4432d',
|
|
||||||
'', 'dark', '30409f', false, 'old.reddit.com', '', '', 0, 0,
|
|
||||||
0, 0, '', 'Verified', 0, false, '', ''),
|
|
||||||
('AutoBetter', '', extract(epoch from now()), 0, true, true, '', '', 0, false,
|
|
||||||
0, 'AutoBetter', '', 'hot', 'top', 'day', '62ca56', 'e4432d',
|
|
||||||
'', 'dark', '30409f', false, 'old.reddit.com', '', '', 0, 0,
|
|
||||||
0, 0, '', 'Verified', 0, false, '', ''),
|
|
||||||
('AutoChoice', '', extract(epoch from now()), 0, true, true, '', '', 0, false,
|
|
||||||
0, 'AutoChoice', '', 'hot', 'top', 'day', '62ca56', 'e4432d',
|
|
||||||
'', 'dark', '30409f', false, 'old.reddit.com', '', '', 0, 0,
|
|
||||||
0, 0, '', 'Verified', 0, false, '', '');
|
|
||||||
|
|
||||||
INSERT INTO public.marseys VALUES
|
INSERT INTO public.marseys VALUES
|
||||||
('marseylaugh',1,'lmao reaction point funny haha lol judgment',0),
|
('marseylaugh',1,'lmao reaction point funny haha lol judgment',0),
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
CREATE TABLE public.submission_options (
|
||||||
|
id integer PRIMARY KEY,
|
||||||
|
submission_id integer NOT NULL,
|
||||||
|
body_html character varying(500) NOT NULL,
|
||||||
|
exclusive boolean NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX option_submission ON public.submission_options USING btree (submission_id);
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.submission_options
|
||||||
|
ADD CONSTRAINT option_submission_fkey FOREIGN KEY (submission_id) REFERENCES public.submissions(id) MATCH FULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.submission_option_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.submission_options ALTER COLUMN id SET DEFAULT nextval('public.submission_option_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE public.submission_option_votes (
|
||||||
|
option_id integer NOT NULL,
|
||||||
|
user_id integer NOT NULL,
|
||||||
|
created_utc integer NOT NULL,
|
||||||
|
submission_id integer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.submission_option_votes
|
||||||
|
ADD CONSTRAINT submission_option_votes_pkey PRIMARY KEY (option_id, user_id);
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.submission_option_votes
|
||||||
|
ADD CONSTRAINT vote_option_fkey FOREIGN KEY (option_id) REFERENCES public.submission_options(id) MATCH FULL;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.submission_option_votes
|
||||||
|
ADD CONSTRAINT vote_user_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) MATCH FULL;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.submission_option_votes
|
||||||
|
ADD CONSTRAINT vote_submission_fkey FOREIGN KEY (submission_id) REFERENCES public.submissions(id) MATCH FULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE public.comment_options (
|
||||||
|
id integer PRIMARY KEY,
|
||||||
|
comment_id integer NOT NULL,
|
||||||
|
body_html character varying(500) NOT NULL,
|
||||||
|
exclusive boolean NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX option_comment ON public.comment_options USING btree (comment_id);
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.comment_options
|
||||||
|
ADD CONSTRAINT option_comment_fkey FOREIGN KEY (comment_id) REFERENCES public.comments(id) MATCH FULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.comment_option_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.comment_options ALTER COLUMN id SET DEFAULT nextval('public.comment_option_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE public.comment_option_votes (
|
||||||
|
option_id integer NOT NULL,
|
||||||
|
user_id integer NOT NULL,
|
||||||
|
created_utc integer NOT NULL,
|
||||||
|
comment_id integer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.comment_option_votes
|
||||||
|
ADD CONSTRAINT comment_option_votes_pkey PRIMARY KEY (option_id, user_id);
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.comment_option_votes
|
||||||
|
ADD CONSTRAINT vote_option_fkey FOREIGN KEY (option_id) REFERENCES public.comment_options(id) MATCH FULL;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.comment_option_votes
|
||||||
|
ADD CONSTRAINT vote_user_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) MATCH FULL;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.comment_option_votes
|
||||||
|
ADD CONSTRAINT vote_comment_fkey FOREIGN KEY (comment_id) REFERENCES public.comments(id) MATCH FULL;
|
Loading…
Reference in New Issue