rDrama/files/classes/cron/submission.py
justcool393 39ce6a4ee9
invisibleify completely removed trees only (fixes #431) (#535)
* invisibleify completely removed trees only (fixes #431)

* fix visibility state for shadowbanned users.
this also ends up moving some of the complexity out of the templates.

* comments: remove unused variable

* moderation state machine

* no seriously this really should check for v not being None

* fix shadowban state

* fix visibility state

* update stateful counters

* don't use bespoke function for show_descendants

* properly mock ModerationState for cron submissions

* fix approval discrepency

* remove treenukes for removed comments

* show shadowbans as removed
2023-04-03 04:30:46 -05:00

185 lines
4.9 KiB
Python

import functools
from datetime import datetime
from sqlalchemy.orm import relationship
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.sql.sqltypes import Boolean, Integer, String, Text
from files.classes.cron.tasks import (RepeatableTask, ScheduledTaskType,
TaskRunContext)
from files.classes.submission import Submission
from files.helpers.config.const import SUBMISSION_TITLE_LENGTH_MAXIMUM
from files.helpers.content import ModerationState, body_displayed
from files.helpers.lazy import lazy
from files.helpers.sanitize import filter_emojis_only
__all__ = ('ScheduledSubmissionTask',)
class ScheduledSubmissionTask(RepeatableTask):
__tablename__ = "tasks_repeatable_scheduled_submissions"
__mapper_args__ = {
"polymorphic_identity": int(ScheduledTaskType.SCHEDULED_SUBMISSION),
}
id = Column(Integer, ForeignKey(RepeatableTask.id), primary_key=True)
author_id_submission = Column(Integer, ForeignKey("users.id"), nullable=False)
ghost = Column(Boolean, default=False, nullable=False)
private = Column(Boolean, default=False, nullable=False)
over_18 = Column(Boolean, default=False, nullable=False)
is_bot = Column(Boolean, default=False, nullable=False)
title = Column(String(SUBMISSION_TITLE_LENGTH_MAXIMUM), nullable=False)
url = Column(String)
body = Column(Text)
body_html = Column(Text)
flair = Column(String)
embed_url = Column(String)
author = relationship("User", foreign_keys=author_id_submission)
task = relationship(RepeatableTask)
submissions = relationship(Submission,
back_populates="task", order_by="Submission.id.desc()")
def run_task(self, ctx:TaskRunContext) -> None:
submission:Submission = self.make_submission(ctx)
with ctx.app_context():
# TODO: stop using app context (currently required for sanitize and
# username pings)
submission.submit(ctx.db) # TODO: thumbnails
submission.publish()
def make_submission(self, ctx:TaskRunContext) -> Submission:
title:str = self.make_title(ctx.trigger_time)
title_html:str = filter_emojis_only(title, graceful=True)
if len(title_html) > 1500: raise ValueError("Rendered title too large")
return Submission(
created_utc=int(ctx.trigger_time.timestamp()),
private=self.private,
author_id=self.author_id_submission,
over_18=self.over_18,
app_id=None,
is_bot =self.is_bot,
title=title,
title_html=title_html,
url=self.url,
body=self.body,
body_html=self.body_html,
flair=self.flair,
ghost=self.ghost,
filter_state='normal',
embed_url=self.embed_url,
task_id=self.id,
)
def make_title(self, trigger_time:datetime) -> str:
return trigger_time.strftime(self.title)
# properties below here are mocked in order to reuse part of the submission
# HTML template for previewing a submitted task
@property
def deleted_utc(self) -> int:
return int(not self.task.enabled)
@functools.cached_property
def title_html(self) -> str:
'''
This is used as a mock property for display in submission listings that
contain scheduled posts.
.. warning::
This property should not be used for generating the HTML for an actual
submission as this will be missing the special formatting that may be
applies to titles. Instead call
`ScheduledSubmissionContext.make_title()` with the `datetime` that the
event was triggered at.
'''
return filter_emojis_only(self.title)
@property
def author_name(self) -> str:
return self.author.username
@property
def upvotes(self) -> int:
return 1
@property
def score(self) -> int:
return 1
@property
def downvotes(self) -> int:
return 0
@property
def realupvotes(self) -> int:
return 1
@property
def comment_count(self) -> int:
return 0
@property
def views(self) -> int:
return 0
@property
def filter_state(self) -> str:
return 'normal'
def award_count(self, kind):
return 0
@lazy
def realurl(self, v):
return Submission.realurl(self, v)
def realbody(self, v):
return body_displayed(self, v, is_html=True)
def plainbody(self, v):
return body_displayed(self, v, is_html=False)
@lazy
def realtitle(self, v):
return self.title_html if self.title_html else self.title
@lazy
def plaintitle(self, v):
return self.title
@property
def permalink(self):
return f"/tasks/scheduled_posts/{self.id}"
@property
def shortlink(self):
return self.permalink
@property
def is_real_submission(self) -> bool:
return False
@property
def should_hide_score(self) -> bool:
return True
@property
def edit_url(self) -> str:
return f"/tasks/scheduled_posts/{self.id}/content"
@property
def moderation_state(self) -> ModerationState:
return ModerationState(
removed=False,
removed_by_name=None,
deleted=False, # we only want to show deleted UI color if disabled
reports_ignored=False,
filtered=False,
op_shadowbanned=False,
op_id=self.author_id_submission,
op_name_safe=self.author_name
)