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)
|
||||
awarded_utc = Column(Integer)
|
||||
|
||||
user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", viewonly=True)
|
||||
post = relationship("Submission", primaryjoin="AwardRelationship.submission_id==Submission.id", viewonly=True)
|
||||
comment = relationship("Comment", primaryjoin="AwardRelationship.comment_id==Comment.id", viewonly=True)
|
||||
user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", back_populates="awards")
|
||||
post = relationship("Submission", primaryjoin="AwardRelationship.submission_id==Submission.id", back_populates="awards")
|
||||
comment = relationship("Comment", primaryjoin="AwardRelationship.comment_id==Comment.id", back_populates="awards")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<AwardRelationship(id={self.id})>"
|
||||
|
||||
@property
|
||||
@lazy
|
||||
|
|
|
@ -29,8 +29,8 @@ class Badge(Base):
|
|||
url = Column(String)
|
||||
created_utc = Column(Integer)
|
||||
|
||||
user = relationship("User", viewonly=True)
|
||||
badge = relationship("BadgeDef", primaryjoin="foreign(Badge.badge_id) == remote(BadgeDef.id)", viewonly=True)
|
||||
user = relationship("User", back_populates="badges")
|
||||
badge = relationship("BadgeDef", primaryjoin="foreign(Badge.badge_id) == remote(BadgeDef.id)")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs:
|
||||
|
|
|
@ -19,9 +19,10 @@ class OauthApp(Base):
|
|||
description = Column(String)
|
||||
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
|
||||
|
@ -36,7 +37,8 @@ class OauthApp(Base):
|
|||
|
||||
@property
|
||||
@lazy
|
||||
def permalink(self): return f"/admin/app/{self.id}"
|
||||
def permalink(self):
|
||||
return f"/admin/app/{self.id}"
|
||||
|
||||
@lazy
|
||||
def idlist(self, page=1):
|
||||
|
@ -70,8 +72,11 @@ class ClientAuth(Base):
|
|||
oauth_client = Column(Integer, ForeignKey("oauth_apps.id"), primary_key=True)
|
||||
access_token = Column(String)
|
||||
|
||||
user = relationship("User", viewonly=True)
|
||||
application = relationship("OauthApp", viewonly=True)
|
||||
user = relationship("User")
|
||||
application = relationship("OauthApp")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ClientAuth(user_id={self.user_id}, oauth_client={self.oauth_client})>"
|
||||
|
||||
@property
|
||||
@lazy
|
||||
|
|
|
@ -76,14 +76,15 @@ class Comment(Base):
|
|||
wordle_result = Column(String)
|
||||
treasure_amount = Column(String)
|
||||
|
||||
oauth_app = relationship("OauthApp", viewonly=True)
|
||||
post = relationship("Submission", viewonly=True)
|
||||
oauth_app = relationship("OauthApp")
|
||||
post = relationship("Submission", back_populates="comments")
|
||||
author = relationship("User", primaryjoin="User.id==Comment.author_id")
|
||||
senttouser = relationship("User", primaryjoin="User.id==Comment.sentto", viewonly=True)
|
||||
parent_comment = relationship("Comment", remote_side=[id], viewonly=True)
|
||||
child_comments = relationship("Comment", lazy="dynamic", remote_side=[parent_comment_id], viewonly=True)
|
||||
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", viewonly=True)
|
||||
flags = relationship("CommentFlag", order_by="CommentFlag.created_utc", viewonly=True)
|
||||
senttouser = relationship("User", primaryjoin="User.id==Comment.sentto")
|
||||
parent_comment = relationship("Comment", remote_side=[id], back_populates="child_comments")
|
||||
child_comments = relationship("Comment", remote_side=[parent_comment_id], back_populates="parent_comment")
|
||||
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", back_populates="comment")
|
||||
flags = relationship("CommentFlag", order_by="CommentFlag.created_utc")
|
||||
options = relationship("CommentOption", order_by="CommentOption.id")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs:
|
||||
|
@ -99,35 +100,6 @@ class Comment(Base):
|
|||
def top_comment(self):
|
||||
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
|
||||
@lazy
|
||||
|
@ -239,8 +211,7 @@ class Comment(Base):
|
|||
if not self.parent_submission:
|
||||
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 = sort_comments(sort, comments)
|
||||
comments = self.child_comments
|
||||
return [x for x in comments if not x.author.shadowbanned]
|
||||
|
||||
|
||||
|
@ -250,8 +221,7 @@ class Comment(Base):
|
|||
if not self.parent_submission:
|
||||
return self.child_comments.order_by(Comment.id).all()
|
||||
|
||||
comments = self.child_comments.filter(Comment.author_id.notin_(poll_bots))
|
||||
return sort_comments(sort, comments).all()
|
||||
return self.child_comments
|
||||
|
||||
|
||||
@property
|
||||
|
@ -405,27 +375,25 @@ class Comment(Base):
|
|||
self.upvotes += amount
|
||||
g.db.add(self)
|
||||
|
||||
for c in self.options:
|
||||
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 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)
|
||||
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.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.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}','comment')"'''
|
||||
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/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)))):
|
||||
body += f"<hr>{self.author.sig_html}"
|
||||
|
|
|
@ -5,4 +5,7 @@ class BannedDomain(Base):
|
|||
|
||||
__tablename__ = "banneddomains"
|
||||
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)
|
||||
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):
|
||||
return f"<Exile(user_id={self.user_id}, sub={self.sub})>"
|
|
@ -15,7 +15,7 @@ class Flag(Base):
|
|||
reason = Column(String)
|
||||
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):
|
||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||
|
@ -48,7 +48,7 @@ class CommentFlag(Base):
|
|||
reason = Column(String)
|
||||
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):
|
||||
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)
|
||||
created_utc = Column(Integer)
|
||||
|
||||
user = relationship("User", uselist=False, primaryjoin="User.id==Follow.user_id", viewonly=True)
|
||||
target = relationship("User", primaryjoin="User.id==Follow.target_id", viewonly=True)
|
||||
user = relationship("User", uselist=False, primaryjoin="User.id==Follow.user_id", back_populates="following")
|
||||
target = relationship("User", uselist=False, primaryjoin="User.id==Follow.target_id", back_populates="followers")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
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)
|
||||
winner_id = Column(Integer, ForeignKey("users.id"))
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Lottery(id={self.id})>"
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def timeleft(self):
|
||||
|
|
|
@ -18,9 +18,9 @@ class ModAction(Base):
|
|||
_note=Column(String)
|
||||
created_utc = Column(Integer)
|
||||
|
||||
user = relationship("User", primaryjoin="User.id==ModAction.user_id", viewonly=True)
|
||||
target_user = relationship("User", primaryjoin="User.id==ModAction.target_user_id", viewonly=True)
|
||||
target_post = relationship("Submission", viewonly=True)
|
||||
user = relationship("User", primaryjoin="User.id==ModAction.user_id")
|
||||
target_user = relationship("User", primaryjoin="User.id==ModAction.target_user_id")
|
||||
target_post = relationship("Submission")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||
|
|
|
@ -12,8 +12,8 @@ class Notification(Base):
|
|||
read = Column(Boolean, default=False)
|
||||
created_utc = Column(Integer)
|
||||
|
||||
comment = relationship("Comment", viewonly=True)
|
||||
user = relationship("User", viewonly=True)
|
||||
comment = relationship("Comment")
|
||||
user = relationship("User")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
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)
|
||||
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):
|
||||
|
@ -17,4 +19,7 @@ class CommentSaveRelationship(Base):
|
|||
__tablename__="comment_save_relationship"
|
||||
|
||||
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)
|
||||
css = Column(String)
|
||||
|
||||
blocks = relationship("SubBlock",
|
||||
primaryjoin="SubBlock.sub==Sub.name", viewonly=True)
|
||||
followers = relationship("SubSubscription",
|
||||
primaryjoin="SubSubscription.sub==Sub.name", viewonly=True)
|
||||
blocks = relationship("SubBlock", primaryjoin="SubBlock.sub==Sub.name")
|
||||
followers = relationship("SubSubscription", primaryjoin="SubSubscription.sub==Sub.name")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Sub(name={self.name})>"
|
||||
|
|
|
@ -16,6 +16,7 @@ from .saves import SaveRelationship
|
|||
from .sub import *
|
||||
from .subscriptions import *
|
||||
from .votes import CommentVote
|
||||
from .polls import *
|
||||
from flask import g
|
||||
|
||||
def sort_posts(sort, posts):
|
||||
|
@ -72,12 +73,13 @@ class Submission(Base):
|
|||
new = Column(Boolean)
|
||||
|
||||
author = relationship("User", primaryjoin="Submission.author_id==User.id")
|
||||
oauth_app = relationship("OauthApp", viewonly=True)
|
||||
approved_by = relationship("User", uselist=False, primaryjoin="Submission.is_approved==User.id", viewonly=True)
|
||||
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", viewonly=True)
|
||||
flags = relationship("Flag", order_by="Flag.created_utc", viewonly=True)
|
||||
comments = relationship("Comment", primaryjoin="Comment.parent_submission==Submission.id")
|
||||
subr = relationship("Sub", primaryjoin="foreign(Submission.sub)==remote(Sub.name)", viewonly=True)
|
||||
oauth_app = relationship("OauthApp")
|
||||
approved_by = relationship("User", uselist=False, primaryjoin="Submission.is_approved==User.id")
|
||||
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", back_populates="post")
|
||||
flags = relationship("Flag", order_by="Flag.created_utc")
|
||||
comments = relationship("Comment", primaryjoin="Comment.parent_submission==Submission.id", back_populates="post")
|
||||
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()))
|
||||
|
||||
|
@ -94,43 +96,6 @@ class Submission(Base):
|
|||
if self.downvotes > 5 and 0.25 < self.upvotes / self.downvotes < 4: return True
|
||||
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
|
||||
@lazy
|
||||
|
@ -401,44 +366,31 @@ class Submission(Base):
|
|||
self.upvotes += amount
|
||||
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"'
|
||||
if c.poll_voted(v): body += " checked"
|
||||
if v: body += f''' onchange="poll_vote('{c.id}', '{self.id}')"'''
|
||||
if c.voted(v): body += " checked"
|
||||
if v: body += f''' onchange="poll_vote('{c.id}', 'post')"'''
|
||||
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 = ''
|
||||
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>"
|
||||
body += f'"> - <a href="/votes/post/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)))):
|
||||
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
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class Subscription(Base):
|
|||
user_id = Column(Integer, ForeignKey("users.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):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
|
|
@ -135,16 +135,16 @@ class User(Base):
|
|||
total_held_lottery_tickets = Column(Integer, default=0)
|
||||
total_lottery_winnings = Column(Integer, default=0)
|
||||
|
||||
badges = relationship("Badge", order_by="Badge.created_utc", viewonly=True)
|
||||
subscriptions = relationship("Subscription", viewonly=True)
|
||||
following = relationship("Follow", primaryjoin="Follow.user_id==User.id", viewonly=True)
|
||||
followers = relationship("Follow", primaryjoin="Follow.target_id==User.id", viewonly=True)
|
||||
viewers = relationship("ViewerRelationship", primaryjoin="User.id == ViewerRelationship.user_id", viewonly=True)
|
||||
blocking = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.user_id", viewonly=True)
|
||||
blocked = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.target_id", viewonly=True)
|
||||
authorizations = relationship("ClientAuth", viewonly=True)
|
||||
awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", viewonly=True)
|
||||
referrals = relationship("User", viewonly=True)
|
||||
badges = relationship("Badge", order_by="Badge.created_utc", back_populates="user")
|
||||
subscriptions = relationship("Subscription", back_populates="user")
|
||||
following = relationship("Follow", primaryjoin="Follow.user_id==User.id", back_populates="user")
|
||||
followers = relationship("Follow", primaryjoin="Follow.target_id==User.id", back_populates="target")
|
||||
viewers = relationship("ViewerRelationship", primaryjoin="User.id == ViewerRelationship.user_id")
|
||||
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", back_populates="target")
|
||||
authorizations = relationship("ClientAuth", back_populates="user")
|
||||
awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", back_populates="user")
|
||||
referrals = relationship("User")
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
|
@ -157,6 +157,10 @@ class User(Base):
|
|||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return f"<User(id={self.id})>"
|
||||
|
||||
|
||||
@lazy
|
||||
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())
|
||||
|
|
|
@ -8,8 +8,8 @@ class UserBlock(Base):
|
|||
user_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)
|
||||
target = relationship("User", primaryjoin="User.id==UserBlock.target_id", viewonly=True)
|
||||
user = relationship("User", primaryjoin="User.id==UserBlock.user_id", back_populates="blocking")
|
||||
target = relationship("User", primaryjoin="User.id==UserBlock.target_id", back_populates="blocked")
|
||||
|
||||
def __repr__(self):
|
||||
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)
|
||||
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):
|
||||
|
||||
|
@ -21,6 +21,9 @@ class ViewerRelationship(Base):
|
|||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ViewerRelationship(user_id={self.user_id}, viewer_id={self.viewer_id})>"
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def last_view_since(self):
|
||||
|
|
|
@ -16,8 +16,8 @@ class Vote(Base):
|
|||
real = Column(Boolean, default=True)
|
||||
created_utc = Column(Integer)
|
||||
|
||||
user = relationship("User", lazy="subquery", viewonly=True)
|
||||
post = relationship("Submission", lazy="subquery", viewonly=True)
|
||||
user = relationship("User", lazy="subquery")
|
||||
post = relationship("Submission", lazy="subquery")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||
|
@ -62,7 +62,7 @@ class CommentVote(Base):
|
|||
created_utc = Column(Integer)
|
||||
|
||||
user = relationship("User", lazy="subquery")
|
||||
comment = relationship("Comment", lazy="subquery", viewonly=True)
|
||||
comment = relationship("Comment", lazy="subquery")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||
|
|
|
@ -155,9 +155,6 @@ AUTOJANNY_ID = 2
|
|||
SNAPPY_ID = 3
|
||||
LONGPOSTBOT_ID = 4
|
||||
ZOZBOT_ID = 5
|
||||
AUTOPOLLER_ID = 6
|
||||
AUTOBETTER_ID = 7
|
||||
AUTOCHOICE_ID = 8
|
||||
BASEDBOT_ID = 0
|
||||
|
||||
SCHIZO_ID = 0
|
||||
|
@ -203,9 +200,6 @@ if SITE in {'rdrama.net', 'devrama.xyz'}:
|
|||
SNAPPY_ID = 261
|
||||
LONGPOSTBOT_ID = 1832
|
||||
ZOZBOT_ID = 1833
|
||||
AUTOPOLLER_ID = 6176
|
||||
AUTOBETTER_ID = 7668
|
||||
AUTOCHOICE_ID = 9167
|
||||
|
||||
SCHIZO_ID = 8494
|
||||
A_ID = 1230
|
||||
|
@ -254,9 +248,6 @@ elif SITE == 'pcmemes.net':
|
|||
SNAPPY_ID = 261
|
||||
LONGPOSTBOT_ID = 1832
|
||||
ZOZBOT_ID = 1833
|
||||
AUTOPOLLER_ID = 2129
|
||||
AUTOBETTER_ID = 1867
|
||||
AUTOCHOICE_ID = 2072
|
||||
BASEDBOT_ID = 800
|
||||
|
||||
KIPPY_ID = 1592
|
||||
|
@ -313,9 +304,7 @@ elif SITE == 'lgbdropthet.com':
|
|||
else: # localhost or testing environment implied
|
||||
pass
|
||||
|
||||
poll_bots = AUTOPOLLER_ID, AUTOBETTER_ID, AUTOCHOICE_ID
|
||||
|
||||
bots = {NOTIFICATIONS_ID, AUTOJANNY_ID, SNAPPY_ID, LONGPOSTBOT_ID, ZOZBOT_ID, BASEDBOT_ID}.union(poll_bots)
|
||||
bots = {NOTIFICATIONS_ID, AUTOJANNY_ID, SNAPPY_ID, LONGPOSTBOT_ID, ZOZBOT_ID, BASEDBOT_ID}
|
||||
|
||||
IMGUR_KEY = environ.get("IMGUR_KEY").strip()
|
||||
PUSHER_ID = environ.get("PUSHER_ID", "").strip()
|
||||
|
|
|
@ -144,7 +144,13 @@ def get_post(i, v=None, graceful=False, rendered=False):
|
|||
)
|
||||
|
||||
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()
|
||||
|
||||
|
@ -196,7 +202,12 @@ def get_posts(pids, v=None):
|
|||
blocked,
|
||||
blocked.c.user_id == Submission.author_id,
|
||||
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]
|
||||
for i in range(len(output)):
|
||||
|
|
|
@ -16,4 +16,5 @@ from .feeds import *
|
|||
from .awards import *
|
||||
from .giphy 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.filter(
|
||||
Comment.top_comment_id == c.top_comment_id,
|
||||
Comment.author_id.notin_(poll_bots)
|
||||
Comment.top_comment_id == c.top_comment_id
|
||||
).join(
|
||||
votes,
|
||||
votes.c.comment_id == Comment.id,
|
||||
|
@ -365,30 +364,20 @@ def api_comment(v):
|
|||
else: c.top_comment_id = parent.top_comment_id
|
||||
|
||||
for option in options:
|
||||
c_option = Comment(author_id=AUTOPOLLER_ID,
|
||||
parent_submission=parent_submission,
|
||||
parent_comment_id=c.id,
|
||||
level=level+1,
|
||||
option = CommentOption(
|
||||
comment_id=c.id,
|
||||
body_html=filter_emojis_only(option),
|
||||
upvotes=0,
|
||||
is_bot=True,
|
||||
ghost=c.ghost
|
||||
)
|
||||
|
||||
g.db.add(c_option)
|
||||
exclusive=False
|
||||
)
|
||||
g.db.add(option)
|
||||
|
||||
for choice in choices:
|
||||
c_choice = Comment(author_id=AUTOCHOICE_ID,
|
||||
parent_submission=parent_submission,
|
||||
parent_comment_id=c.id,
|
||||
level=level+1,
|
||||
choice = CommentOption(
|
||||
comment_id=c.id,
|
||||
body_html=filter_emojis_only(choice),
|
||||
upvotes=0,
|
||||
is_bot=True,
|
||||
ghost=c.ghost
|
||||
)
|
||||
|
||||
g.db.add(c_choice)
|
||||
exclusive=True
|
||||
)
|
||||
g.db.add(choice)
|
||||
|
||||
if request.host == 'pcmemes.net' and c.body.lower().startswith("based"):
|
||||
pill = based_regex.match(body)
|
||||
|
@ -664,29 +653,21 @@ def edit_comment(cid, v):
|
|||
|
||||
for i in poll_regex.finditer(body):
|
||||
body = body.replace(i.group(0), "")
|
||||
c_option = Comment(author_id=AUTOPOLLER_ID,
|
||||
parent_submission=c.parent_submission,
|
||||
parent_comment_id=c.id,
|
||||
level=c.level+1,
|
||||
option = CommentOption(
|
||||
comment_id=c.id,
|
||||
body_html=filter_emojis_only(i.group(1)),
|
||||
upvotes=0,
|
||||
is_bot=True,
|
||||
ghost=c.ghost
|
||||
)
|
||||
g.db.add(c_option)
|
||||
exclusive = False
|
||||
)
|
||||
g.db.add(option)
|
||||
|
||||
for i in choice_regex.finditer(body):
|
||||
body = body.replace(i.group(0), "")
|
||||
c_choice = Comment(author_id=AUTOCHOICE_ID,
|
||||
parent_submission=c.parent_submission,
|
||||
parent_comment_id=c.id,
|
||||
level=c.level+1,
|
||||
option = CommentOption(
|
||||
comment_id=c.id,
|
||||
body_html=filter_emojis_only(i.group(1)),
|
||||
upvotes=0,
|
||||
is_bot=True,
|
||||
ghost=c.ghost
|
||||
)
|
||||
g.db.add(c_choice)
|
||||
exclusive = True
|
||||
)
|
||||
g.db.add(option)
|
||||
|
||||
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())
|
||||
|
|
|
@ -463,9 +463,7 @@ def all_comments(v):
|
|||
@cache.memoize(timeout=86400)
|
||||
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_(excluded))
|
||||
comments = g.db.query(Comment.id).filter(Comment.parent_submission != None, Comment.author_id.notin_(v.userblocks))
|
||||
|
||||
if v.admin_level < 2:
|
||||
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))
|
||||
|
||||
users_count = g.db.query(User).count()
|
||||
if users_count == 8:
|
||||
if users_count == 5:
|
||||
admin_level=3
|
||||
session["history"] = []
|
||||
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):
|
||||
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.c.comment_id == Comment.id,
|
||||
isouter=True
|
||||
|
@ -170,7 +170,13 @@ def post_id(pid, anything=None, v=None, sub=None):
|
|||
blocked,
|
||||
blocked.c.user_id == Comment.author_id,
|
||||
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 = []
|
||||
for c in comments.all():
|
||||
|
@ -192,7 +198,7 @@ def post_id(pid, anything=None, v=None, sub=None):
|
|||
else:
|
||||
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)
|
||||
|
||||
|
@ -268,7 +274,7 @@ def viewmore(v, pid, sort, offset):
|
|||
votes.c.vote_type,
|
||||
blocking.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):
|
||||
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()]
|
||||
comments = first + second
|
||||
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)
|
||||
|
||||
|
@ -427,27 +433,22 @@ def edit_post(pid, v):
|
|||
|
||||
for i in poll_regex.finditer(body):
|
||||
body = body.replace(i.group(0), "")
|
||||
c = Comment(author_id=AUTOPOLLER_ID,
|
||||
parent_submission=p.id,
|
||||
level=1,
|
||||
option = SubmissionOption(
|
||||
submission_id=p.id,
|
||||
body_html=filter_emojis_only(i.group(1)),
|
||||
upvotes=0,
|
||||
is_bot=True,
|
||||
ghost=p.ghost
|
||||
)
|
||||
g.db.add(c)
|
||||
exclusive = False
|
||||
)
|
||||
g.db.add(option)
|
||||
|
||||
for i in choice_regex.finditer(body):
|
||||
body = body.replace(i.group(0), "")
|
||||
c = Comment(author_id=AUTOCHOICE_ID,
|
||||
parent_submission=p.id,
|
||||
level=1,
|
||||
option = SubmissionOption(
|
||||
submission_id=p.id,
|
||||
body_html=filter_emojis_only(i.group(1)),
|
||||
upvotes=0,
|
||||
is_bot=True,
|
||||
ghost=p.ghost
|
||||
)
|
||||
g.db.add(c)
|
||||
exclusive = True
|
||||
)
|
||||
g.db.add(option)
|
||||
|
||||
|
||||
body_html = sanitize(body, edit=True)
|
||||
|
||||
|
@ -974,26 +975,20 @@ def submit_post(v, sub=None):
|
|||
g.db.add(bet_option)
|
||||
|
||||
for option in options:
|
||||
c = Comment(author_id=AUTOPOLLER_ID,
|
||||
parent_submission=post.id,
|
||||
level=1,
|
||||
option = SubmissionOption(
|
||||
submission_id=post.id,
|
||||
body_html=filter_emojis_only(option),
|
||||
upvotes=0,
|
||||
is_bot=True,
|
||||
ghost=post.ghost
|
||||
)
|
||||
g.db.add(c)
|
||||
exclusive=False
|
||||
)
|
||||
g.db.add(option)
|
||||
|
||||
for choice in choices:
|
||||
c = Comment(author_id=AUTOCHOICE_ID,
|
||||
parent_submission=post.id,
|
||||
level=1,
|
||||
choice = SubmissionOption(
|
||||
submission_id=post.id,
|
||||
body_html=filter_emojis_only(choice),
|
||||
upvotes=0,
|
||||
is_bot=True,
|
||||
ghost=post.ghost
|
||||
)
|
||||
g.db.add(c)
|
||||
exclusive=True
|
||||
)
|
||||
g.db.add(choice)
|
||||
|
||||
vote = Vote(user_id=v.id,
|
||||
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()
|
||||
|
||||
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))
|
||||
|
||||
|
|
|
@ -6,12 +6,9 @@ from flask import *
|
|||
from files.__main__ import app, limiter, cache
|
||||
from os import environ
|
||||
|
||||
@app.get("/votes")
|
||||
@app.get("/votes/<linK>")
|
||||
@auth_required
|
||||
def admin_vote_info_get(v):
|
||||
link = request.values.get("link")
|
||||
if not link: return render_template("votes.html", v=v)
|
||||
|
||||
def vote_info_get(v, link):
|
||||
try:
|
||||
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)
|
||||
|
@ -20,8 +17,6 @@ def admin_vote_info_get(v):
|
|||
|
||||
if thing.ghost and v.id != AEVANN_ID: abort(403)
|
||||
|
||||
if not thing.author:
|
||||
print(thing.id, flush=True)
|
||||
if isinstance(thing, Submission):
|
||||
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]
|
||||
|
@ -151,8 +146,6 @@ def api_vote_comment(comment_id, new, v):
|
|||
except: abort(404)
|
||||
|
||||
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()
|
||||
|
||||
|
@ -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()
|
||||
if comment.author.progressivestack: comment.realupvotes *= 2
|
||||
g.db.add(comment)
|
||||
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
|
||||
return "", 204
|
|
@ -443,7 +443,7 @@
|
|||
|
||||
{% 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>
|
||||
|
||||
|
@ -646,7 +646,7 @@
|
|||
<div class="modal-body">
|
||||
<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>
|
||||
|
||||
|
|
|
@ -142,11 +142,11 @@ Text 2
|
|||
<td>
|
||||
<div class="custom-control">
|
||||
<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 class="custom-control">
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -161,11 +161,11 @@ Text 2
|
|||
<td>
|
||||
<div class="custom-control">
|
||||
<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 class="custom-control">
|
||||
<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>
|
||||
</td>
|
||||
</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 %}
|
||||
|
||||
|
||||
{% 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 %}
|
||||
<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 %}
|
||||
|
||||
|
||||
{% 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>
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ set CACHE_VER = {
|
|||
|
||||
'js/award_modal.js': 253,
|
||||
'js/bootstrap.js': 272,
|
||||
'js/comments+submission_listing.js': 261,
|
||||
'js/comments+submission_listing.js': 262,
|
||||
'js/submission_listing.js': 261,
|
||||
'js/emoji_modal.js': 297,
|
||||
'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,
|
||||
0, 'zozbot', '', 'hot', 'top', 'day', '62ca56', 'e4432d',
|
||||
'', 'dark', '30409f', false, 'old.reddit.com', '', '', 0, 0,
|
||||
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, '', '');
|
||||
0, 0, '', 'Verified', 0, false, '/i/pfps/5.webp', '/i/pfps/5.webp');
|
||||
|
||||
INSERT INTO public.marseys VALUES
|
||||
('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