Volunteer Janitor: Initial duty acquisition.
This commit is contained in:
parent
e43db0535d
commit
03b323c7a1
7 changed files with 149 additions and 6 deletions
|
@ -110,6 +110,7 @@ class User(Base):
|
||||||
original_username = deferred(Column(String))
|
original_username = deferred(Column(String))
|
||||||
referred_by = Column(Integer, ForeignKey("users.id"))
|
referred_by = Column(Integer, ForeignKey("users.id"))
|
||||||
subs_created = Column(Integer, default=0, nullable=False)
|
subs_created = Column(Integer, default=0, nullable=False)
|
||||||
|
volunteer_last_started_utc = Column(DateTime, nullable=True)
|
||||||
|
|
||||||
Index(
|
Index(
|
||||||
'users_original_username_trgm_idx',
|
'users_original_username_trgm_idx',
|
||||||
|
|
|
@ -1,16 +1,46 @@
|
||||||
|
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from files.__main__ import app
|
from files.__main__ import app
|
||||||
from files.classes.user import User
|
from files.classes.user import User
|
||||||
import files.helpers.jinja2
|
import files.helpers.jinja2
|
||||||
from files.helpers.wrappers import auth_required
|
from files.helpers.wrappers import auth_required
|
||||||
from flask import render_template
|
from flask import render_template, g
|
||||||
|
import sqlalchemy
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from files.routes.volunteer_common import VolunteerDuty
|
||||||
|
import files.routes.volunteer_janitor
|
||||||
|
|
||||||
|
@files.helpers.jinja2.template_function
|
||||||
|
def volunteer_available_for(u: Optional[User]) -> bool:
|
||||||
|
return volunteer_get_duty(u) is not None
|
||||||
|
|
||||||
|
def volunteer_get_duty(u: Optional[User]) -> Optional[VolunteerDuty]:
|
||||||
|
if u is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# check to make sure it's at least 20h since the last volunteer
|
||||||
|
if (u.volunteer_last_started_utc is not None) and (datetime.now() - u.volunteer_last_started_utc) < timedelta(hours = 20):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# TODO: clever code that figures out the most important duty available
|
||||||
|
janitor = files.routes.volunteer_janitor.get_duty(u)
|
||||||
|
if janitor is not None:
|
||||||
|
return janitor
|
||||||
|
|
||||||
|
# oh well
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@app.get("/volunteer")
|
@app.get("/volunteer")
|
||||||
@auth_required
|
@auth_required
|
||||||
def volunteer(v: User):
|
def volunteer(v: User):
|
||||||
return render_template("volunteer.html", v=v)
|
duty = volunteer_get_duty(v)
|
||||||
|
|
||||||
|
if duty is not None:
|
||||||
|
duty.accept()
|
||||||
|
v.volunteer_last_started_utc = sqlalchemy.func.now()
|
||||||
|
g.db.add(v)
|
||||||
|
g.db.commit()
|
||||||
|
|
||||||
@files.helpers.jinja2.template_function
|
return render_template("volunteer.html", v=v, duty=duty)
|
||||||
def volunteer_available_for(u: User) -> bool:
|
|
||||||
return True
|
|
||||||
|
|
12
files/routes/volunteer_common.py
Normal file
12
files/routes/volunteer_common.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
class VolunteerDuty(ABC):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def accept(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def embed_template(self) -> str:
|
||||||
|
return ""
|
58
files/routes/volunteer_janitor.py
Normal file
58
files/routes/volunteer_janitor.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
from files.classes.comment import Comment
|
||||||
|
from files.classes.flags import CommentFlag
|
||||||
|
from files.classes.user import User
|
||||||
|
from files.routes.volunteer_common import VolunteerDuty
|
||||||
|
from flask import g
|
||||||
|
import pprint
|
||||||
|
import random
|
||||||
|
|
||||||
|
class VolunteerDutyJanitor(VolunteerDuty):
|
||||||
|
|
||||||
|
def __init__(self, choices):
|
||||||
|
self.choices = choices
|
||||||
|
|
||||||
|
def accept(self) -> None:
|
||||||
|
pprint.pprint(self.choices)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def embed_template(self) -> str:
|
||||||
|
return "volunteer_janitor.html"
|
||||||
|
|
||||||
|
def get_duty(u: User) -> VolunteerDutyJanitor:
|
||||||
|
|
||||||
|
# these could probably be combined into one query somehow
|
||||||
|
|
||||||
|
# find reported comments not made by the current user
|
||||||
|
reported_comments = g.db.query(Comment) \
|
||||||
|
.where(Comment.filter_state == 'reported') \
|
||||||
|
.where(Comment.author_id != u.id) \
|
||||||
|
.with_entities(Comment.id)
|
||||||
|
|
||||||
|
reported_ids = [reported.id for reported in reported_comments]
|
||||||
|
|
||||||
|
# find distinguished children of those reported comments
|
||||||
|
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)
|
||||||
|
|
||||||
|
final_reported = [report.comment_id for report in nonuser_reports]
|
||||||
|
|
||||||
|
if len(final_reported) <= 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return VolunteerDutyJanitor(random.sample(final_reported, k = min(3, len(final_reported))))
|
|
@ -5,7 +5,18 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
hello! welcome to the volunteering
|
hello! welcome to the volunteering
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if duty == None %}
|
||||||
|
<div>
|
||||||
|
there is no volunteering to do, but thanks
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div>
|
||||||
|
{% from duty.embed_template() import display %}
|
||||||
|
{{ display(duty) }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
3
files/templates/volunteer_janitor.html
Normal file
3
files/templates/volunteer_janitor.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{% macro display(duty) %}
|
||||||
|
janny
|
||||||
|
{% endmacro %}
|
|
@ -0,0 +1,28 @@
|
||||||
|
"""Add per-user field for the last usage of the Volunteer page
|
||||||
|
|
||||||
|
Revision ID: d7a4a6723411
|
||||||
|
Revises: b23ec080ecb7
|
||||||
|
Create Date: 2022-11-14 11:24:55.304258+00:00
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'd7a4a6723411'
|
||||||
|
down_revision = 'b23ec080ecb7'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('users', sa.Column('volunteer_last_started_utc', sa.DateTime(), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('users', 'volunteer_last_started_utc')
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Add table
Add a link
Reference in a new issue