forked from rDrama/rDrama
1
0
Fork 0

Merge pull request #66 from Aevann1/polls

Polls
master
Aevann1 2021-10-06 02:05:15 +02:00 committed by GitHub
commit 4ea8cb58aa
11 changed files with 120 additions and 39 deletions

View File

@ -2,7 +2,8 @@ import re
from urllib.parse import urlencode, urlparse, parse_qs from urllib.parse import urlencode, urlparse, parse_qs
from flask import * from flask import *
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship, deferred from sqlalchemy.orm import relationship, deferred, lazyload
from files.classes.votes import CommentVote
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from files.helpers.const import SLURS from files.helpers.const import SLURS
from files.__main__ import Base from files.__main__ import Base
@ -37,7 +38,7 @@ class Comment(Base):
notifiedto=Column(Integer) notifiedto=Column(Integer)
app_id = Column(Integer, ForeignKey("oauth_apps.id")) app_id = Column(Integer, ForeignKey("oauth_apps.id"))
oauth_app = relationship("OauthApp", viewonly=True) oauth_app = relationship("OauthApp", viewonly=True)
upvotes = Column(Integer, default=1) upvotes = Column(Integer, default=0)
downvotes = Column(Integer, default=0) downvotes = Column(Integer, default=0)
body = deferred(Column(String(10000))) body = deferred(Column(String(10000)))
body_html = deferred(Column(String(20000))) body_html = deferred(Column(String(20000)))
@ -61,6 +62,13 @@ class Comment(Base):
return f"<Comment(id={self.id})>" return f"<Comment(id={self.id})>"
def poll_voted(self, v):
if v:
vote = g.db.query(CommentVote).options(lazyload('*')).filter_by(user_id=v.id, comment_id=self.id).first()
if vote: return vote.vote_type
else: return None
else: return None
@property @property
@lazy @lazy
def created_datetime(self): def created_datetime(self):

View File

@ -4,9 +4,9 @@ from sqlalchemy.orm import relationship, deferred
import re, random import re, random
from urllib.parse import urlparse from urllib.parse import urlparse
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from files.helpers.const import SLURS from files.helpers.const import SLURS, AUTOPOLLER_ACCOUNT
from files.__main__ import Base from files.__main__ import Base
from .flags import * from .flags import Flag
from os import environ from os import environ
import time import time
@ -35,11 +35,8 @@ class Submission(Base):
private = Column(Boolean, default=False) private = Column(Boolean, default=False)
club = Column(Boolean, default=False) club = Column(Boolean, default=False)
comment_count = Column(Integer, default=0) comment_count = Column(Integer, default=0)
comments = relationship("Comment", primaryjoin="Comment.parent_submission==Submission.id", viewonly=True)
flags = relationship("Flag", lazy="dynamic", viewonly=True)
is_approved = Column(Integer, ForeignKey("users.id"), default=0) is_approved = Column(Integer, ForeignKey("users.id"), default=0)
over_18 = Column(Boolean, default=False) over_18 = Column(Boolean, default=False)
author = relationship("User", primaryjoin="Submission.author_id==User.id")
is_bot = Column(Boolean, default=False) is_bot = Column(Boolean, default=False)
upvotes = Column(Integer, default=1) upvotes = Column(Integer, default=1)
downvotes = Column(Integer, default=0) downvotes = Column(Integer, default=0)
@ -52,6 +49,9 @@ class Submission(Base):
ban_reason = Column(String(128)) ban_reason = Column(String(128))
embed_url = Column(String(256)) embed_url = Column(String(256))
comments = relationship("Comment", lazy="dynamic", primaryjoin="Comment.parent_submission==Submission.id", viewonly=True)
flags = relationship("Flag", lazy="dynamic", viewonly=True)
author = relationship("User", primaryjoin="Submission.author_id==User.id")
oauth_app = relationship("OauthApp", viewonly=True) oauth_app = relationship("OauthApp", viewonly=True)
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", viewonly=True)
awards = relationship("AwardRelationship", viewonly=True) awards = relationship("AwardRelationship", viewonly=True)
@ -71,6 +71,16 @@ class Submission(Base):
return f"<Submission(id={self.id})>" return f"<Submission(id={self.id})>"
@property
@lazy
def options(self):
return self.comments.filter_by(author_id = AUTOPOLLER_ACCOUNT)
@property
@lazy
def created_datetime(self):
return str(time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(self.created_utc)))
@property @property
@lazy @lazy
def created_datetime(self): def created_datetime(self):

View File

@ -165,6 +165,7 @@ NOTIFICATIONS_ACCOUNT = 1046
if site == "pcmemes.net": AUTOJANNY_ACCOUNT = 1050 if site == "pcmemes.net": AUTOJANNY_ACCOUNT = 1050
else: AUTOJANNY_ACCOUNT = 2360 else: AUTOJANNY_ACCOUNT = 2360
LONGPOSTBOT_ACCOUNT = 1832 LONGPOSTBOT_ACCOUNT = 1832
AUTOPOLLER_ACCOUNT = 6176
PUSHER_INSTANCE_ID = '02ddcc80-b8db-42be-9022-44c546b4dce6' PUSHER_INSTANCE_ID = '02ddcc80-b8db-42be-9022-44c546b4dce6'
PUSHER_KEY = environ.get("PUSHER_KEY", "").strip() PUSHER_KEY = environ.get("PUSHER_KEY", "").strip()

View File

@ -286,6 +286,7 @@ def api_comment(v):
body=body[:10000] body=body[:10000]
) )
c.upvotes = 1
g.db.add(c) g.db.add(c)
g.db.flush() g.db.flush()
@ -562,13 +563,14 @@ def api_comment(v):
) )
g.db.add(vote) g.db.add(vote)
cache.delete_memoized(comment_idlist) cache.delete_memoized(comment_idlist)
v.comment_count = g.db.query(Comment.id).options(lazyload('*')).filter(Comment.author_id == v.id, Comment.parent_submission != None).filter_by(is_banned=False, deleted_utc=0).count() v.comment_count = g.db.query(Comment.id).options(lazyload('*')).filter(Comment.author_id == v.id, Comment.parent_submission != None).filter_by(is_banned=False, deleted_utc=0).count()
g.db.add(v) g.db.add(v)
parent_post.comment_count = g.db.query(Comment.id).options(lazyload('*')).filter_by(parent_submission=parent_post.id).count() parent_post.comment_count += 1
g.db.add(parent_post) g.db.add(parent_post)
c.voted = 1 c.voted = 1

View File

@ -123,7 +123,8 @@ def post_id(pid, anything=None, v=None):
comments = comments.filter(Comment.author_id.notin_(shadowbanned)) comments = comments.filter(Comment.author_id.notin_(shadowbanned))
comments=comments.filter( comments=comments.filter(
Comment.parent_submission == post.id Comment.parent_submission == post.id,
Comment.author_id != AUTOPOLLER_ACCOUNT,
).join( ).join(
votes, votes,
votes.c.comment_id == Comment.id, votes.c.comment_id == Comment.id,
@ -161,7 +162,7 @@ def post_id(pid, anything=None, v=None):
else: else:
shadowbanned = [x[0] for x in g.db.query(User.id).options(lazyload('*')).filter(User.shadowbanned != None).all()] shadowbanned = [x[0] for x in g.db.query(User.id).options(lazyload('*')).filter(User.shadowbanned != None).all()]
comments = g.db.query(Comment).filter(Comment.parent_submission == post.id, Comment.author_id.notin_(shadowbanned)) comments = g.db.query(Comment).filter(Comment.parent_submission == post.id, Comment.author_id != AUTOPOLLER_ACCOUNT, Comment.author_id.notin_(shadowbanned))
if sort == "new": if sort == "new":
comments = comments.order_by(Comment.created_utc.desc()) comments = comments.order_by(Comment.created_utc.desc())
@ -730,9 +731,17 @@ def submit_post(v):
for i in re.finditer('^(https:\/\/.*\.(png|jpg|jpeg|gif|webp|PNG|JPG|JPEG|GIF|WEBP|9999))', body, re.MULTILINE): for i in re.finditer('^(https:\/\/.*\.(png|jpg|jpeg|gif|webp|PNG|JPG|JPEG|GIF|WEBP|9999))', body, re.MULTILINE):
if "wikipedia" not in i.group(1): body = body.replace(i.group(1), f'![]({i.group(1)})') if "wikipedia" not in i.group(1): body = body.replace(i.group(1), f'![]({i.group(1)})')
body = re.sub('([^\n])\n([^\n])', r'\1\n\n\2', body) body = re.sub('([^\n])\n([^\n])', r'\1\n\n\2', body)
options = []
for i in re.finditer('\s*\$([^\$]+)\$\s*', body):
options.append(i.group(1))
body = body.replace(i.group(0), "")
body_md = CustomRenderer().render(mistletoe.Document(body)) body_md = CustomRenderer().render(mistletoe.Document(body))
body_html = sanitize(body_md) body_html = sanitize(body_md)
if len(body_html) > 20000: abort(400) if len(body_html) > 20000: abort(400)
# Run safety filter # Run safety filter
@ -806,6 +815,16 @@ def submit_post(v):
g.db.add(new_post) g.db.add(new_post)
g.db.flush() g.db.flush()
for option in options:
c = Comment(author_id=AUTOPOLLER_ACCOUNT,
parent_submission=new_post.id,
level=1,
body=option,
)
g.db.add(c)
g.db.flush()
vote = Vote(user_id=v.id, vote = Vote(user_id=v.id,
vote_type=1, vote_type=1,
submission_id=new_post.id submission_id=new_post.id

View File

@ -160,4 +160,34 @@ def api_vote_comment(comment_id, new, v):
g.db.add(comment) g.db.add(comment)
g.db.commit() g.db.commit()
except: g.db.rollback() except: g.db.rollback()
return "", 204
@app.post("/vote/poll/<comment_id>")
@auth_required
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).options(lazyload('*')).filter_by(user_id=v.id, comment_id=comment.id).first()
if existing and existing.vote_type == vote: return "", 204
if existing:
existing.vote_type = new
g.db.add(existing)
else:
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.id).options(lazyload('*')).filter_by(comment_id=comment.id, vote_type=1).count()
g.db.add(comment)
g.db.commit()
return "", 204 return "", 204

View File

@ -33,14 +33,14 @@
{% if v %} {% if v %}
{% include "award_modal.html" %} {% include "award_modal.html" %}
<script src="/assets/js/comments_v.js?v=8"></script> <script src="/assets/js/comments_v.js?v=11"></script>
{% endif %} {% endif %}
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js"></script>
{% if v and v.admin_level == 6 %} {% if v and v.admin_level == 6 %}
<script src="/assets/js/comments_admin.js?v=1"></script> <script src="/assets/js/comments_admin.js?v=2"></script>
{% endif %} {% endif %}
<script> <script>

View File

@ -1,33 +1,19 @@
<script> <script>
function post(url, callback, errortext) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
var form = new FormData()
form.append("formkey", formkey());
xhr.withCredentials=true;
xhr.onerror=function() { alert(errortext); };
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
callback();
} else {
xhr.onerror();
}
};
xhr.send(form);
};
function delete_postModal(id) { function delete_postModal(id) {
function delete_post(){ function delete_post(){
this.innerHTML='<span class="spinner-border spinner-border-sm mr-2" role="status" aria-hidden="true"></span>Deleting post'; this.innerHTML='<span class="spinner-border spinner-border-sm mr-2" role="status" aria-hidden="true"></span>Deleting post';
this.disabled = true; this.disabled = true;
post('/delete_post/' + id,
callback = function() {
location.reload(); var url = '/delete_post/' + id
} var xhr = new XMLHttpRequest();
) xhr.open("POST", url, true);
var form = new FormData()
form.append("formkey", formkey());
xhr.withCredentials=true;
xhr.send(form);
location.reload();
} }
document.getElementById("deletePostButton-mobile").onclick = delete_post; document.getElementById("deletePostButton-mobile").onclick = delete_post;

View File

@ -1,4 +1,4 @@
<script src="/assets/js/gif_modal.js?v=5"></script> <script src="/assets/js/gif_modal.js?v=6"></script>
<div class="modal fade" id="gifModal" tabindex="-1" role="dialog" aria-labelledby="gifModalTitle" aria-hidden="true"> <div class="modal fade" id="gifModal" tabindex="-1" role="dialog" aria-labelledby="gifModalTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered p-5" role="document"> <div class="modal-dialog modal-dialog-scrollable modal-dialog-centered p-5" role="document">

View File

@ -6,7 +6,7 @@
{% include "emoji_modal.html" %} {% include "emoji_modal.html" %}
{% include "gif_modal.html" %} {% include "gif_modal.html" %}
<script src="/assets/js/setting_profile.js?v=1"></script> <script src="/assets/js/settings_profile.js?v=2"></script>
<div id="posts" class="row"> <div id="posts" class="row">

View File

@ -15,9 +15,25 @@
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js"></script>
<script src="/assets/js/new_comments_count.js?v=1"></script> <script src="/assets/js/new_comments_count.js?v=1"></script>
<script>
function poll_vote(cid) {
{% if v %}
var type = document.getElementById(cid).checked;
var scoretext = document.getElementById('poll-' + cid);
var score = Number(scoretext.textContent);
if (type == true) scoretext.textContent = score + 1;
else scoretext.textContent = score - 1;
post('/vote/poll/' + cid + '?vote=' + type);
{% else %}
var myToast = new bootstrap.Toast(document.getElementById('toast-post-error'));
myToast.show();
document.getElementById('toast-post-error-text').innerText = "Only logged-in users can vote!";
{% endif %}
}
</script>
{% if v and v.id == p.author_id %} {% if v and v.id == p.author_id %}
<script> <script>
togglePostEdit=function(id){ togglePostEdit=function(id){
body=document.getElementById("post-body"); body=document.getElementById("post-body");
@ -34,9 +50,9 @@
{% endif %} {% endif %}
{% if 'marsey.tech' in request.host %} {% if 'rdrama' not in request.host %}
{% if v %} {% if v %}
<script src="/assets/js/comments_v.js?v=8"></script> <script src="/assets/js/comments_v.js?v=11"></script>
{% include "award_modal.html" %} {% include "award_modal.html" %}
{% include "emoji_modal.html" %} {% include "emoji_modal.html" %}
{% include "gif_modal.html" %} {% include "gif_modal.html" %}
@ -357,6 +373,15 @@
<pre></pre> <pre></pre>
{% endif %} {% endif %}
{{p.realbody(v) | safe}} {{p.realbody(v) | safe}}
{% for c in p.options %}
<div class="custom-control">
<input type="checkbox" class="custom-control-input" id="{{c.id}}" name="option" {% if c.poll_voted(v) %}checked{% endif %} onchange="poll_vote('{{c.id}}')">
<label class="custom-control-label" for="{{c.id}}">{{c.body}} - <a href="/votes?link=t3_{{c.id}}"><span id="poll-{{c.id}}">{{c.upvotes}}</span> votes</a></label>
</div>
{% endfor %}
</div> </div>
{% if p.embed_url %} {% if p.embed_url %}