mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-02-02 16:21:32 -08:00
refactor voting code to enable api development #13
This commit is contained in:
parent
30dedd19c5
commit
740c42daea
4 changed files with 182 additions and 293 deletions
|
@ -20,15 +20,14 @@ from app.models import User, Community, CommunityJoinRequest, CommunityMember, C
|
|||
ChatMessage, Conversation, UserFollower, UserBlock, Poll, PollChoice
|
||||
from app.activitypub.util import public_key, users_total, active_half_year, active_month, local_posts, local_comments, \
|
||||
post_to_activity, find_actor_or_create, instance_blocked, find_reply_parent, find_liked_object, \
|
||||
lemmy_site_data, instance_weight, is_activitypub_request, downvote_post_reply, downvote_post, upvote_post_reply, \
|
||||
upvote_post, delete_post_or_comment, community_members, \
|
||||
lemmy_site_data, is_activitypub_request, delete_post_or_comment, community_members, \
|
||||
user_removed_from_remote_server, create_post, create_post_reply, update_post_reply_from_activity, \
|
||||
update_post_from_activity, undo_vote, undo_downvote, post_to_page, get_redis_connection, find_reported_object, \
|
||||
process_report, ensure_domains_match, can_edit, can_delete, remove_data_from_banned_user, resolve_remote_post, \
|
||||
inform_followers_of_post_update, comment_model_to_json, restore_post_or_comment, ban_local_user, unban_local_user, \
|
||||
lock_post
|
||||
from app.utils import gibberish, get_setting, is_image_url, allowlist_html, render_template, \
|
||||
domain_from_url, markdown_to_html, community_membership, ap_datetime, ip_address, can_downvote, \
|
||||
from app.utils import gibberish, get_setting, render_template, \
|
||||
community_membership, ap_datetime, ip_address, can_downvote, \
|
||||
can_upvote, can_create_post, awaken_dormant_instance, shorten_string, can_create_post_reply, sha256_digest, \
|
||||
community_moderators, lemmy_markdown_to_html
|
||||
|
||||
|
@ -780,11 +779,8 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
# insert into voted table
|
||||
if liked is None:
|
||||
activity_log.exception_message = 'Liked object not found'
|
||||
elif liked is not None and isinstance(liked, Post):
|
||||
upvote_post(liked, user)
|
||||
activity_log.result = 'success'
|
||||
elif liked is not None and isinstance(liked, PostReply):
|
||||
upvote_post_reply(liked, user)
|
||||
elif liked is not None and isinstance(liked, (Post, PostReply)):
|
||||
liked.vote(user, 'upvote')
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Could not detect type of like'
|
||||
|
@ -813,10 +809,7 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
if disliked is None:
|
||||
activity_log.exception_message = 'Liked object not found'
|
||||
elif isinstance(disliked, (Post, PostReply)):
|
||||
if isinstance(disliked, Post):
|
||||
downvote_post(disliked, user)
|
||||
elif isinstance(disliked, PostReply):
|
||||
downvote_post_reply(disliked, user)
|
||||
disliked.vote(user, 'downvote')
|
||||
activity_log.result = 'success'
|
||||
# todo: recalculate 'hotness' of liked post/reply
|
||||
else:
|
||||
|
@ -1152,11 +1145,8 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
# insert into voted table
|
||||
if liked is None:
|
||||
activity_log.exception_message = 'Liked object not found'
|
||||
elif liked is not None and isinstance(liked, Post):
|
||||
upvote_post(liked, user)
|
||||
activity_log.result = 'success'
|
||||
elif liked is not None and isinstance(liked, PostReply):
|
||||
upvote_post_reply(liked, user)
|
||||
elif liked is not None and isinstance(liked, (Post, PostReply)):
|
||||
liked.vote(user, 'upvote')
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Could not detect type of like'
|
||||
|
@ -1186,10 +1176,7 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
if disliked is None:
|
||||
activity_log.exception_message = 'Liked object not found'
|
||||
elif isinstance(disliked, (Post, PostReply)):
|
||||
if isinstance(disliked, Post):
|
||||
downvote_post(disliked, user)
|
||||
elif isinstance(disliked, PostReply):
|
||||
downvote_post_reply(disliked, user)
|
||||
disliked.vote(user, 'downvote')
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Could not detect type of like'
|
||||
|
|
|
@ -1302,169 +1302,6 @@ def is_activitypub_request():
|
|||
return 'application/ld+json' in request.headers.get('Accept', '') or 'application/activity+json' in request.headers.get('Accept', '')
|
||||
|
||||
|
||||
def downvote_post(post, user):
|
||||
user.last_seen = utcnow()
|
||||
user.recalculate_attitude()
|
||||
existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=post.id).first()
|
||||
if not existing_vote:
|
||||
effect = -1.0
|
||||
post.down_votes += 1
|
||||
# Make 'hot' sort more spicy by amplifying the effect of early downvotes
|
||||
if post.up_votes + post.down_votes <= 30:
|
||||
effect = current_app.config['SPICY_UNDER_30']
|
||||
elif post.up_votes + post.down_votes <= 60:
|
||||
effect = current_app.config['SPICY_UNDER_60']
|
||||
else:
|
||||
effect = -1.0
|
||||
if user.cannot_vote():
|
||||
effect = 0
|
||||
post.score -= effect
|
||||
vote = PostVote(user_id=user.id, post_id=post.id, author_id=post.author.id,
|
||||
effect=effect)
|
||||
post.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
else:
|
||||
# remove previously cast upvote
|
||||
if existing_vote.effect > 0:
|
||||
post.author.reputation -= existing_vote.effect
|
||||
post.up_votes -= 1
|
||||
post.score -= existing_vote.effect
|
||||
db.session.delete(existing_vote)
|
||||
|
||||
# apply down vote
|
||||
effect = -1.0
|
||||
post.down_votes += 1
|
||||
post.score -= 1.0
|
||||
vote = PostVote(user_id=user.id, post_id=post.id, author_id=post.author.id,
|
||||
effect=effect)
|
||||
post.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
else:
|
||||
pass # they have already downvoted this post
|
||||
post.ranking = post_ranking(post.score, post.posted_at)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def downvote_post_reply(comment, user):
|
||||
user.last_seen = utcnow()
|
||||
user.recalculate_attitude()
|
||||
existing_vote = PostReplyVote.query.filter_by(user_id=user.id,
|
||||
post_reply_id=comment.id).first()
|
||||
if not existing_vote:
|
||||
effect = -1.0
|
||||
comment.down_votes += 1
|
||||
if user.cannot_vote():
|
||||
effect = 0
|
||||
comment.score -= effect
|
||||
vote = PostReplyVote(user_id=user.id, post_reply_id=comment.id,
|
||||
author_id=comment.author.id, effect=effect)
|
||||
comment.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
else:
|
||||
# remove previously cast upvote
|
||||
if existing_vote.effect > 0:
|
||||
comment.author.reputation -= existing_vote.effect
|
||||
comment.up_votes -= 1
|
||||
comment.score -= existing_vote.effect
|
||||
db.session.delete(existing_vote)
|
||||
|
||||
# apply down vote
|
||||
effect = -1.0
|
||||
comment.down_votes += 1
|
||||
comment.score -= 1.0
|
||||
vote = PostReplyVote(user_id=user.id, post_reply_id=comment.id,
|
||||
author_id=comment.author.id, effect=effect)
|
||||
comment.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
else:
|
||||
pass # they have already downvoted this reply
|
||||
comment.ranking = confidence(comment.up_votes, comment.down_votes)
|
||||
|
||||
|
||||
def upvote_post_reply(comment, user):
|
||||
user.last_seen = utcnow()
|
||||
user.recalculate_attitude()
|
||||
effect = instance_weight(user.ap_domain)
|
||||
existing_vote = PostReplyVote.query.filter_by(user_id=user.id,
|
||||
post_reply_id=comment.id).first()
|
||||
if user.cannot_vote():
|
||||
effect = 0
|
||||
if not existing_vote:
|
||||
comment.up_votes += 1
|
||||
comment.score += effect
|
||||
vote = PostReplyVote(user_id=user.id, post_reply_id=comment.id,
|
||||
author_id=comment.author.id, effect=effect)
|
||||
if comment.community.low_quality and effect > 0:
|
||||
effect = 0
|
||||
comment.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
else:
|
||||
# remove previously cast downvote
|
||||
if existing_vote.effect < 0:
|
||||
comment.author.reputation -= existing_vote.effect
|
||||
comment.down_votes -= 1
|
||||
comment.score -= existing_vote.effect
|
||||
db.session.delete(existing_vote)
|
||||
|
||||
# apply up vote
|
||||
comment.up_votes += 1
|
||||
comment.score += effect
|
||||
vote = PostReplyVote(user_id=user.id, post_reply_id=comment.id,
|
||||
author_id=comment.author.id, effect=effect)
|
||||
if comment.community.low_quality and effect > 0:
|
||||
effect = 0
|
||||
comment.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
else:
|
||||
pass # they have already upvoted this reply
|
||||
comment.ranking = confidence(comment.up_votes, comment.down_votes)
|
||||
|
||||
|
||||
def upvote_post(post, user):
|
||||
user.last_seen = utcnow()
|
||||
user.recalculate_attitude()
|
||||
effect = instance_weight(user.ap_domain)
|
||||
# Make 'hot' sort more spicy by amplifying the effect of early upvotes
|
||||
spicy_effect = effect
|
||||
if post.up_votes + post.down_votes <= 10:
|
||||
spicy_effect = effect * current_app.config['SPICY_UNDER_10']
|
||||
elif post.up_votes + post.down_votes <= 30:
|
||||
spicy_effect = effect * current_app.config['SPICY_UNDER_30']
|
||||
elif post.up_votes + post.down_votes <= 60:
|
||||
spicy_effect = effect * current_app.config['SPICY_UNDER_60']
|
||||
if user.cannot_vote():
|
||||
effect = spicy_effect = 0
|
||||
existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=post.id).first()
|
||||
if not existing_vote:
|
||||
post.up_votes += 1
|
||||
post.score += spicy_effect
|
||||
vote = PostVote(user_id=user.id, post_id=post.id, author_id=post.author.id,
|
||||
effect=effect)
|
||||
if post.community.low_quality and effect > 0:
|
||||
effect = 0
|
||||
post.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
else:
|
||||
# remove previous cast downvote
|
||||
if existing_vote.effect < 0:
|
||||
post.author.reputation -= existing_vote.effect
|
||||
post.down_votes -= 1
|
||||
post.score -= existing_vote.effect
|
||||
db.session.delete(existing_vote)
|
||||
|
||||
# apply up vote
|
||||
post.up_votes += 1
|
||||
post.score += effect
|
||||
vote = PostVote(user_id=user.id, post_id=post.id, author_id=post.author.id,
|
||||
effect=effect)
|
||||
if post.community.low_quality and effect > 0:
|
||||
effect = 0
|
||||
post.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
post.ranking = post_ranking(post.score, post.posted_at)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def delete_post_or_comment(user_ap_id, community_ap_id, to_be_deleted_ap_id):
|
||||
if current_app.debug:
|
||||
delete_post_or_comment_task(user_ap_id, community_ap_id, to_be_deleted_ap_id)
|
||||
|
|
171
app/models.py
171
app/models.py
|
@ -101,6 +101,14 @@ class Instance(db.Model):
|
|||
return db.session.execute(text('SELECT COUNT(id) as c FROM "user" WHERE instance_id = :instance_id'),
|
||||
{'instance_id': self.id}).scalar()
|
||||
|
||||
@classmethod
|
||||
def weight(cls, domain: str):
|
||||
if domain:
|
||||
instance = Instance.query.filter_by(domain=domain).first()
|
||||
if instance:
|
||||
return instance.vote_weight
|
||||
return 1.0
|
||||
|
||||
def __repr__(self):
|
||||
return '<Instance {}>'.format(self.domain)
|
||||
|
||||
|
@ -1154,6 +1162,96 @@ class Post(db.Model):
|
|||
'name': f'#{tag.name}'})
|
||||
return return_value
|
||||
|
||||
# All the following post/comment ranking math is explained at https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9
|
||||
epoch = datetime(1970, 1, 1)
|
||||
|
||||
def epoch_seconds(self, date):
|
||||
td = date - self.epoch
|
||||
return td.days * 86400 + td.seconds + (float(td.microseconds) / 1000000)
|
||||
|
||||
# All the following post/comment ranking math is explained at https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9
|
||||
def post_ranking(self, score, date: datetime):
|
||||
if date is None:
|
||||
date = datetime.utcnow()
|
||||
if score is None:
|
||||
score = 1
|
||||
order = math.log(max(abs(score), 1), 10)
|
||||
sign = 1 if score > 0 else -1 if score < 0 else 0
|
||||
seconds = self.epoch_seconds(date) - 1685766018
|
||||
return round(sign * order + seconds / 45000, 7)
|
||||
|
||||
def vote(self, user: User, vote_direction: str):
|
||||
assert vote_direction == 'upvote' or vote_direction == 'downvote'
|
||||
existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=self.id).first()
|
||||
undo = None
|
||||
if existing_vote:
|
||||
if not self.community.low_quality:
|
||||
self.author.reputation -= existing_vote.effect
|
||||
if existing_vote.effect > 0: # previous vote was up
|
||||
if vote_direction == 'upvote': # new vote is also up, so remove it
|
||||
db.session.delete(existing_vote)
|
||||
self.up_votes -= 1
|
||||
self.score -= existing_vote.effect
|
||||
undo = 'Like'
|
||||
else: # new vote is down while previous vote was up, so reverse their previous vote
|
||||
existing_vote.effect = -1
|
||||
self.up_votes -= 1
|
||||
self.down_votes += 1
|
||||
self.score -= existing_vote.effect * 2
|
||||
else: # previous vote was down
|
||||
if vote_direction == 'downvote': # new vote is also down, so remove it
|
||||
db.session.delete(existing_vote)
|
||||
self.down_votes -= 1
|
||||
self.score += existing_vote.effect
|
||||
undo = 'Dislike'
|
||||
else: # new vote is up while previous vote was down, so reverse their previous vote
|
||||
existing_vote.effect = 1
|
||||
self.up_votes += 1
|
||||
self.down_votes -= 1
|
||||
self.score += existing_vote.effect * 2
|
||||
else:
|
||||
if vote_direction == 'upvote':
|
||||
effect = Instance.weight(user.ap_domain)
|
||||
spicy_effect = effect
|
||||
# Make 'hot' sort more spicy by amplifying the effect of early upvotes
|
||||
if self.up_votes + self.down_votes <= 10:
|
||||
spicy_effect = effect * current_app.config['SPICY_UNDER_10']
|
||||
elif self.up_votes + self.down_votes <= 30:
|
||||
spicy_effect = effect * current_app.config['SPICY_UNDER_30']
|
||||
elif self.up_votes + self.down_votes <= 60:
|
||||
spicy_effect = effect * current_app.config['SPICY_UNDER_60']
|
||||
if user.cannot_vote():
|
||||
effect = spicy_effect = 0
|
||||
self.up_votes += 1
|
||||
self.score += spicy_effect
|
||||
else:
|
||||
effect = -1.0
|
||||
self.down_votes += 1
|
||||
# Make 'hot' sort more spicy by amplifying the effect of early downvotes
|
||||
if self.up_votes + self.down_votes <= 30:
|
||||
effect = current_app.config['SPICY_UNDER_30']
|
||||
elif self.up_votes + self.down_votes <= 60:
|
||||
effect = current_app.config['SPICY_UNDER_60']
|
||||
else:
|
||||
effect = -1.0
|
||||
if user.cannot_vote():
|
||||
effect = 0
|
||||
self.score -= effect
|
||||
vote = PostVote(user_id=user.id, post_id=self.id, author_id=self.author.id,
|
||||
effect=effect)
|
||||
# upvotes do not increase reputation in low quality communities
|
||||
if self.community.low_quality and effect > 0:
|
||||
effect = 0
|
||||
self.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
|
||||
user.last_seen = utcnow()
|
||||
if not user.banned:
|
||||
self.ranking = self.post_ranking(self.score, self.created_at)
|
||||
user.recalculate_attitude()
|
||||
db.session.commit()
|
||||
return undo
|
||||
|
||||
|
||||
class PostReply(db.Model):
|
||||
query_class = FullTextSearchQuery
|
||||
|
@ -1274,6 +1372,79 @@ class PostReply(db.Model):
|
|||
NotificationSubscription.type == NOTIF_REPLY).first()
|
||||
return existing_notification is not None
|
||||
|
||||
# used for ranking comments
|
||||
def _confidence(self, ups, downs):
|
||||
n = ups + downs
|
||||
|
||||
if n == 0:
|
||||
return 0.0
|
||||
|
||||
z = 1.281551565545
|
||||
p = float(ups) / n
|
||||
|
||||
left = p + 1 / (2 * n) * z * z
|
||||
right = z * math.sqrt(p * (1 - p) / n + z * z / (4 * n * n))
|
||||
under = 1 + 1 / n * z * z
|
||||
|
||||
return (left - right) / under
|
||||
|
||||
def confidence(self, ups, downs) -> float:
|
||||
if ups is None or ups < 0:
|
||||
ups = 0
|
||||
if downs is None or downs < 0:
|
||||
downs = 0
|
||||
if ups + downs == 0:
|
||||
return 0.0
|
||||
else:
|
||||
return self._confidence(ups, downs)
|
||||
|
||||
def vote(self, user: User, vote_direction: str):
|
||||
existing_vote = PostReplyVote.query.filter_by(user_id=user.id, post_reply_id=self.id).first()
|
||||
undo = None
|
||||
if existing_vote:
|
||||
if existing_vote.effect > 0: # previous vote was up
|
||||
if vote_direction == 'upvote': # new vote is also up, so remove it
|
||||
db.session.delete(existing_vote)
|
||||
self.up_votes -= 1
|
||||
self.score -= 1
|
||||
undo = 'Like'
|
||||
else: # new vote is down while previous vote was up, so reverse their previous vote
|
||||
existing_vote.effect = -1
|
||||
self.up_votes -= 1
|
||||
self.down_votes += 1
|
||||
self.score -= 2
|
||||
else: # previous vote was down
|
||||
if vote_direction == 'downvote': # new vote is also down, so remove it
|
||||
db.session.delete(existing_vote)
|
||||
self.down_votes -= 1
|
||||
self.score += 1
|
||||
undo = 'Dislike'
|
||||
else: # new vote is up while previous vote was down, so reverse their previous vote
|
||||
existing_vote.effect = 1
|
||||
self.up_votes += 1
|
||||
self.down_votes -= 1
|
||||
self.score += 2
|
||||
else:
|
||||
if user.cannot_vote():
|
||||
effect = 0
|
||||
else:
|
||||
effect = 1
|
||||
if vote_direction == 'upvote':
|
||||
self.up_votes += 1
|
||||
else:
|
||||
effect = effect * -1
|
||||
self.down_votes += 1
|
||||
self.score += effect
|
||||
vote = PostReplyVote(user_id=user.id, post_reply_id=self.id, author_id=self.author.id,
|
||||
effect=effect)
|
||||
self.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
current_user.last_seen = utcnow()
|
||||
self.ranking = self.confidence(self.up_votes, self.down_votes)
|
||||
user.recalculate_attitude()
|
||||
db.session.commit()
|
||||
return undo
|
||||
|
||||
|
||||
class Domain(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
|
|
@ -338,62 +338,7 @@ def show_post(post_id: int):
|
|||
@validation_required
|
||||
def post_vote(post_id: int, vote_direction):
|
||||
post = Post.query.get_or_404(post_id)
|
||||
existing_vote = PostVote.query.filter_by(user_id=current_user.id, post_id=post.id).first()
|
||||
undo = None
|
||||
if existing_vote:
|
||||
if not post.community.low_quality:
|
||||
post.author.reputation -= existing_vote.effect
|
||||
if existing_vote.effect > 0: # previous vote was up
|
||||
if vote_direction == 'upvote': # new vote is also up, so remove it
|
||||
db.session.delete(existing_vote)
|
||||
post.up_votes -= 1
|
||||
post.score -= 1
|
||||
undo = 'Like'
|
||||
else: # new vote is down while previous vote was up, so reverse their previous vote
|
||||
existing_vote.effect = -1
|
||||
post.up_votes -= 1
|
||||
post.down_votes += 1
|
||||
post.score -= 2
|
||||
else: # previous vote was down
|
||||
if vote_direction == 'downvote': # new vote is also down, so remove it
|
||||
db.session.delete(existing_vote)
|
||||
post.down_votes -= 1
|
||||
post.score += 1
|
||||
undo = 'Dislike'
|
||||
else: # new vote is up while previous vote was down, so reverse their previous vote
|
||||
existing_vote.effect = 1
|
||||
post.up_votes += 1
|
||||
post.down_votes -= 1
|
||||
post.score += 2
|
||||
else:
|
||||
if vote_direction == 'upvote':
|
||||
effect = 1
|
||||
post.up_votes += 1
|
||||
# Make 'hot' sort more spicy by amplifying the effect of early upvotes
|
||||
if post.up_votes + post.down_votes <= 10:
|
||||
post.score += current_app.config['SPICY_UNDER_10']
|
||||
elif post.up_votes + post.down_votes <= 30:
|
||||
post.score += current_app.config['SPICY_UNDER_30']
|
||||
elif post.up_votes + post.down_votes <= 60:
|
||||
post.score += current_app.config['SPICY_UNDER_60']
|
||||
else:
|
||||
post.score += 1
|
||||
else:
|
||||
effect = -1
|
||||
post.down_votes += 1
|
||||
if post.up_votes + post.down_votes <= 30:
|
||||
post.score -= current_app.config['SPICY_UNDER_30']
|
||||
elif post.up_votes + post.down_votes <= 60:
|
||||
post.score -= current_app.config['SPICY_UNDER_60']
|
||||
else:
|
||||
post.score -= 1
|
||||
vote = PostVote(user_id=current_user.id, post_id=post.id, author_id=post.author.id,
|
||||
effect=effect)
|
||||
# upvotes do not increase reputation in low quality communities
|
||||
if post.community.low_quality and effect > 0:
|
||||
effect = 0
|
||||
post.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
undo = post.vote(current_user, vote_direction)
|
||||
|
||||
if not post.community.local_only:
|
||||
if undo:
|
||||
|
@ -440,14 +385,6 @@ def post_vote(post_id: int, vote_direction):
|
|||
post_request_in_background(post.community.ap_inbox_url, action_json, current_user.private_key,
|
||||
current_user.public_url(not(post.community.instance.votes_are_public() and current_user.vote_privately())) + '#main-key')
|
||||
|
||||
current_user.last_seen = utcnow()
|
||||
current_user.ip_address = ip_address()
|
||||
if not current_user.banned:
|
||||
post.ranking = post_ranking(post.score, post.created_at)
|
||||
db.session.commit()
|
||||
current_user.recalculate_attitude()
|
||||
db.session.commit()
|
||||
|
||||
recently_upvoted = []
|
||||
recently_downvoted = []
|
||||
if vote_direction == 'upvote' and undo is None:
|
||||
|
@ -467,43 +404,7 @@ def post_vote(post_id: int, vote_direction):
|
|||
@validation_required
|
||||
def comment_vote(comment_id, vote_direction):
|
||||
comment = PostReply.query.get_or_404(comment_id)
|
||||
existing_vote = PostReplyVote.query.filter_by(user_id=current_user.id, post_reply_id=comment.id).first()
|
||||
undo = None
|
||||
if existing_vote:
|
||||
if existing_vote.effect > 0: # previous vote was up
|
||||
if vote_direction == 'upvote': # new vote is also up, so remove it
|
||||
db.session.delete(existing_vote)
|
||||
comment.up_votes -= 1
|
||||
comment.score -= 1
|
||||
undo = 'Like'
|
||||
else: # new vote is down while previous vote was up, so reverse their previous vote
|
||||
existing_vote.effect = -1
|
||||
comment.up_votes -= 1
|
||||
comment.down_votes += 1
|
||||
comment.score -= 2
|
||||
else: # previous vote was down
|
||||
if vote_direction == 'downvote': # new vote is also down, so remove it
|
||||
db.session.delete(existing_vote)
|
||||
comment.down_votes -= 1
|
||||
comment.score += 1
|
||||
undo = 'Dislike'
|
||||
else: # new vote is up while previous vote was down, so reverse their previous vote
|
||||
existing_vote.effect = 1
|
||||
comment.up_votes += 1
|
||||
comment.down_votes -= 1
|
||||
comment.score += 2
|
||||
else:
|
||||
if vote_direction == 'upvote':
|
||||
effect = 1
|
||||
comment.up_votes += 1
|
||||
comment.score += 1
|
||||
else:
|
||||
effect = -1
|
||||
comment.down_votes += 1
|
||||
comment.score -= 1
|
||||
vote = PostReplyVote(user_id=current_user.id, post_reply_id=comment_id, author_id=comment.author.id, effect=effect)
|
||||
comment.author.reputation += effect
|
||||
db.session.add(vote)
|
||||
undo = comment.vote(current_user, vote_direction)
|
||||
|
||||
if not comment.community.local_only:
|
||||
if undo:
|
||||
|
@ -550,13 +451,6 @@ def comment_vote(comment_id, vote_direction):
|
|||
post_request_in_background(comment.community.ap_inbox_url, action_json, current_user.private_key,
|
||||
current_user.public_url(not(comment.community.instance.votes_are_public() and current_user.vote_privately())) + '#main-key')
|
||||
|
||||
current_user.last_seen = utcnow()
|
||||
current_user.ip_address = ip_address()
|
||||
comment.ranking = confidence(comment.up_votes, comment.down_votes)
|
||||
db.session.commit()
|
||||
current_user.recalculate_attitude()
|
||||
db.session.commit()
|
||||
|
||||
recently_upvoted = []
|
||||
recently_downvoted = []
|
||||
if vote_direction == 'upvote' and undo is None:
|
||||
|
|
Loading…
Add table
Reference in a new issue