furmeet-bot/webproj/bot/tasks.py

162 lines
6.1 KiB
Python

import datetime
import random
import sys
import traceback
from background_task import background
from background_task import models as taskmodels
from django.conf import settings
from django.db.models import Count
from django.utils import timezone
from telegram.bot import Bot
from telegram.parsemode import ParseMode
from telegram.error import BadRequest
from ..adminModelRegister import registrableModelsInModule
from typing import List, Type
from . import models
@background()
def captcha_kicker():
captcha_kicker(schedule=5)
for pendingCaptchaUser in models.PendingCaptchaUser.objects.all():
td: datetime.timedelta = (pendingCaptchaUser.created + datetime.timedelta(seconds=pendingCaptchaUser.lifetime)) - timezone.now()
sec_remain = int(td.total_seconds())
if sec_remain < 0:
if sec_remain < -1800:
pendingCaptchaUser.delete()
continue
bot_token = pendingCaptchaUser.bot_token
bot = Bot(token=bot_token)
try:
bot.delete_message(
chat_id=pendingCaptchaUser.group.telegram_id,
message_id=pendingCaptchaUser.captcha_message_id,
)
except:
traceback.print_exc()
try:
bot.kick_chat_member(
chat_id=pendingCaptchaUser.group.telegram_id,
user_id=pendingCaptchaUser.user.telegram_id,
)
except:
traceback.print_exc()
try:
bot.unban_chat_member(
chat_id=pendingCaptchaUser.group.telegram_id,
user_id=pendingCaptchaUser.user.telegram_id,
)
except:
traceback.print_exc()
pendingCaptchaUser.delete()
@background()
def clean_logs():
clean_logs(schedule=200)
TaskModels = [
taskmodels.CompletedTask,
taskmodels.Task,
]
for TaskModel in TaskModels:
for task_name in set(map(lambda a: a['task_name'], TaskModel.objects.values('task_name'))):
for unwanted_object in taskmodels.Task.objects.filter(task_name=task_name).order_by('-id').all()[100:]:
unwanted_object.delete()
@background()
def dispatch_periodic_messages():
dispatch_periodic_messages(schedule=30)
now = timezone.now()
for group_preferences in models.GroupPreferences.objects.filter(planned_message_enabled=True).all():
bot_token = None
pmi = group_preferences.planned_message_issuer
if pmi is not None:
bot_token = pmi.token
else:
bot_token = settings.TELEGRAM_TOKEN
pending_message_dispatch = list(filter(
lambda pmd: False if (tnd := pmd.time_next_dispatch) is None else tnd <= now,
group_preferences.planned_message_dispatches.all(),
))
if len(pending_message_dispatch) > 0:
planned_messages = list(group_preferences.planned_messages.all())
bot = None
for dispatch_request in pending_message_dispatch:
requested_tag_set = set(dispatch_request.tags_as_list)
compatible_messages = list(filter(
lambda planned_message: requested_tag_set.intersection(planned_message.tags_as_list),
planned_messages,
))
if len(compatible_messages) == 0:
compatible_messages = planned_messages
if len(compatible_messages) == 0:
continue
message_to_send = random.choice(compatible_messages)
dispatch_request.time_last_dispatch = now
dispatch_request.save()
if bot is None:
bot = Bot(token=bot_token)
failed = False
try:
bot.send_message(
chat_id=group_preferences.group.telegram_id,
text=message_to_send.message
.replace('&nbsp;', ' ')
.replace('<br>', '')
.replace('<br >', '')
.replace('<br/>', '')
.replace('<br />', ''),
parse_mode=ParseMode.HTML,
)
except:
traceback.print_exc()
failed = True
if failed:
group_preferences.planned_message_fails += 1
if group_preferences.planned_message_fails >= 5:
group_preferences.planned_message_enabled = False
group_preferences.save()
else:
if group_preferences.planned_message_fails > 0:
group_preferences.planned_message_fails = 0
group_preferences.save()
@background()
def dispatch_periodic_deletion():
dispatch_periodic_deletion(schedule=5)
for self_destructing_message in models.SelfDestructingMessage.objects.all():
bot = Bot(self_destructing_message.telegram_bot.token)
try:
bot.delete_message(self_destructing_message.chat_id,
self_destructing_message.message_id)
except:
pass
self_destructing_message.delete()
@background()
def clean_old_objects():
clean_old_objects(schedule=300)
model_list: List[Type[models.models.Model]] = registrableModelsInModule(models)
for model in model_list:
if getattr(model, 'AUTO_COLLECT', False):
collection_timeout_seconds = getattr(model, 'COLLECTION_TIMEOUT', 3600*24*28)
model: Type[models.Timestampable] = model
for obj in model.objects.all():
obj: models.Timestampable = obj
if obj.modified < (timezone.now() - datetime.timedelta(seconds=collection_timeout_seconds)):
obj.delete()
taskmodels.Task.objects.filter().delete()
taskmodels.CompletedTask.objects.filter().delete()
captcha_kicker(schedule=5)
dispatch_periodic_messages(schedule=30)
dispatch_periodic_deletion(schedule=5)
clean_logs(schedule=200)
clean_old_objects(schedule=300)