103 lines
4 KiB
Python
103 lines
4 KiB
Python
|
|
from typing import Optional
|
|
from files.__main__ import app
|
|
from files.classes.comment import Comment
|
|
from files.classes.flags import CommentFlag
|
|
from files.classes.user import User
|
|
from files.classes.visstate import StateReport, StateMod
|
|
from files.classes.volunteer_janitor import VolunteerJanitorRecord, VolunteerJanitorResult
|
|
from files.helpers.volunteer_janitor import update_comment_badness
|
|
from files.routes.volunteer_common import VolunteerDuty
|
|
from flask import g
|
|
import pprint
|
|
import random
|
|
import sqlalchemy
|
|
from sqlalchemy.orm import aliased
|
|
|
|
class VolunteerDutyJanitor(VolunteerDuty):
|
|
|
|
def __init__(self, choices):
|
|
self.choices = choices
|
|
|
|
def accept(self, v) -> None:
|
|
for item in self.choices:
|
|
record = VolunteerJanitorRecord()
|
|
record.user_id = v.id
|
|
record.comment_id = item
|
|
record.result = VolunteerJanitorResult.Pending
|
|
g.db.add(record)
|
|
|
|
g.db.commit()
|
|
|
|
def embed_template(self) -> str:
|
|
return "volunteer_janitor.html"
|
|
|
|
def comments(self) -> list[Comment]:
|
|
return g.db.query(Comment).where(Comment.id.in_(self.choices))
|
|
|
|
|
|
def get_duty(u: User) -> Optional[VolunteerDutyJanitor]:
|
|
if not app.config['VOLUNTEER_JANITOR_ENABLE']:
|
|
return None
|
|
|
|
# these could probably be combined into one query somehow
|
|
|
|
# find reported visible comments not made by the current user or in reply to the current user
|
|
ParentComment = aliased(Comment)
|
|
reported_comments = g.db.query(Comment) \
|
|
.where(Comment.state_report == StateReport.REPORTED) \
|
|
.where(Comment.state_mod == StateMod.VISIBLE) \
|
|
.where(Comment.state_user_deleted_utc == None) \
|
|
.where(Comment.author_id != u.id) \
|
|
.outerjoin(ParentComment, ParentComment.id == Comment.parent_comment_id) \
|
|
.where(sqlalchemy.or_(ParentComment.author_id != u.id, ParentComment.author_id == None)) \
|
|
.with_entities(Comment.id)
|
|
|
|
reported_ids = [reported.id for reported in reported_comments]
|
|
|
|
if not app.config['DBG_VOLUNTEER_PERMISSIVE']:
|
|
# find distinguished children of those reported comments
|
|
# this is a ghastly query and should be fixed when we're doing some kind of cleanup and mod-action formalization
|
|
distinguished_children = g.db.query(Comment) \
|
|
.where(Comment.parent_comment_id.in_(reported_ids)) \
|
|
.where(Comment.distinguish_level > 0) \
|
|
.with_entities(Comment.parent_comment_id)
|
|
|
|
distinguished_children_ids = [child.parent_comment_id for child in distinguished_children]
|
|
|
|
# filter
|
|
# we're doing this because we don't want to give people hints as to the "right" result
|
|
# once a modhat hits, that's it, doesn't show up in the volunteer system anymore
|
|
clean_reported = set(reported_ids) - set(distinguished_children_ids)
|
|
|
|
# also, let's make sure it has a report that isn't made by this user
|
|
nonuser_reports = g.db.query(CommentFlag) \
|
|
.where(CommentFlag.comment_id.in_(clean_reported)) \
|
|
.where(CommentFlag.user_id != u.id) \
|
|
.with_entities(CommentFlag.comment_id)
|
|
|
|
# also, let's make sure it hasn't already been looked at by this user
|
|
seen_records = g.db.query(VolunteerJanitorRecord) \
|
|
.where(VolunteerJanitorRecord.comment_id.in_(nonuser_reports)) \
|
|
.where(VolunteerJanitorRecord.user_id == u.id) \
|
|
.with_entities(VolunteerJanitorRecord.comment_id)
|
|
|
|
final_reported = list({report.comment_id for report in nonuser_reports} - {record.comment_id for record in seen_records})
|
|
else:
|
|
final_reported = reported_ids
|
|
|
|
if len(final_reported) <= 0:
|
|
return None
|
|
|
|
return VolunteerDutyJanitor(random.sample(final_reported, k = min(3, len(final_reported))))
|
|
|
|
def submitted(v: User, key: str, val: str) -> None:
|
|
record = VolunteerJanitorRecord()
|
|
record.user_id = v.id
|
|
record.comment_id = key
|
|
record.result = VolunteerJanitorResult(int(val))
|
|
g.db.add(record)
|
|
|
|
update_comment_badness(g.db, key)
|
|
|
|
g.db.commit()
|