This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
Telegram/modules/scheduled.py

458 lines
18 KiB
Python
Raw Normal View History

2023-01-03 16:12:46 +02:00
"""Automatically register commands and execute
some scheduled tasks is the main idea of this module"""
from asyncio import sleep
2022-12-30 21:36:06 +02:00
from os import listdir, makedirs, path, sep
from traceback import format_exc
2022-12-11 20:51:46 +02:00
from apscheduler.schedulers.asyncio import AsyncIOScheduler
2022-12-18 00:25:53 +02:00
from datetime import datetime, timedelta
from ujson import dumps
2022-12-10 16:52:34 +02:00
from app import app
2023-03-09 17:25:06 +02:00
from pyrogram.types import (
BotCommand,
BotCommandScopeChat,
BotCommandScopeChatAdministrators,
)
2022-12-18 00:36:39 +02:00
from pyrogram.errors import bad_request_400
2022-12-18 00:25:53 +02:00
from pyrogram.enums.chat_members_filter import ChatMembersFilter
2022-12-22 16:05:27 +02:00
from classes.holo_user import HoloUser
2023-01-16 13:09:53 +02:00
from modules.utils import configGet, jsonLoad, jsonSave, locale, logWrite
2022-12-10 16:52:34 +02:00
from dateutil.relativedelta import relativedelta
2023-04-02 17:44:46 +03:00
from modules.database import (
col_applications,
col_sponsorships,
col_youtube,
col_warnings,
)
from xmltodict import parse
from requests import get
2022-12-10 16:52:34 +02:00
2022-12-11 20:51:46 +02:00
scheduler = AsyncIOScheduler()
2022-12-10 16:52:34 +02:00
if configGet("enabled", "scheduler", "cache_members"):
2023-03-09 17:25:06 +02:00
@scheduler.scheduled_job(
trigger="interval", seconds=configGet("interval", "scheduler", "cache_members")
)
async def cache_group_members():
list_of_users = []
2023-01-04 20:59:09 +02:00
async for member in app.get_chat_members(configGet("users", "groups")):
list_of_users.append(member.user.id)
makedirs(configGet("cache", "locations"), exist_ok=True)
2023-03-09 17:25:06 +02:00
jsonSave(
list_of_users, path.join(configGet("cache", "locations"), "group_members")
)
if configGet("debug") is True:
logWrite("User group caching performed", debug=True)
2022-12-30 21:36:06 +02:00
2023-03-09 17:25:06 +02:00
if configGet("enabled", "scheduler", "cache_admins"):
2023-03-09 17:25:06 +02:00
@scheduler.scheduled_job(
trigger="interval", seconds=configGet("interval", "scheduler", "cache_admins")
)
async def cache_admins():
list_of_users = []
2023-01-04 20:14:02 +02:00
async for member in app.get_chat_members(configGet("admin", "groups")):
list_of_users.append(member.user.id)
makedirs(configGet("cache", "locations"), exist_ok=True)
2023-01-04 14:31:42 +02:00
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "admins"))
if configGet("debug") is True:
logWrite("Admin group caching performed", debug=True)
2022-12-30 21:36:06 +02:00
2023-03-09 17:25:06 +02:00
2022-12-18 00:36:39 +02:00
# Cache the avatars of group members
2022-12-18 00:25:53 +02:00
if configGet("enabled", "scheduler", "cache_avatars"):
2023-03-09 17:25:06 +02:00
@scheduler.scheduled_job(
trigger="date", run_date=datetime.now() + timedelta(seconds=15)
)
@scheduler.scheduled_job(
trigger="interval", hours=configGet("interval", "scheduler", "cache_avatars")
)
2022-12-18 00:25:53 +02:00
async def cache_avatars():
list_of_users = []
2023-03-09 17:25:06 +02:00
async for member in app.get_chat_members(
configGet("users", "groups"), filter=ChatMembersFilter.SEARCH, query=""
):
2022-12-18 00:25:53 +02:00
list_of_users.append(member.user)
for user in list_of_users:
if user.photo != None:
2023-03-09 17:25:06 +02:00
if not path.exists(
f'{configGet("cache", "locations")}{sep}avatars{sep}{user.photo.big_file_id}'
):
print(
f"Pre-cached avatar {user.photo.big_file_id} of {user.id}",
flush=True,
)
await app.download_media(
user.photo.big_file_id,
file_name=path.join(
configGet("cache", "locations"),
"avatars",
user.photo.big_file_id,
),
)
2022-12-18 00:25:53 +02:00
logWrite("Avatars caching performed")
2022-12-18 00:36:39 +02:00
# Check for birthdays
2023-01-03 22:36:26 +02:00
if configGet("enabled", "features", "applications") is True:
if configGet("enabled", "scheduler", "birthdays") is True:
2023-03-09 17:25:06 +02:00
@scheduler.scheduled_job(
trigger="cron", hour=configGet("time", "scheduler", "birthdays")
)
2023-01-03 22:36:26 +02:00
async def check_birthdays():
for entry in col_applications.find():
2023-03-09 17:25:06 +02:00
if entry["application"]["2"].strftime(
"%d.%m"
) == datetime.now().strftime("%d.%m"):
2023-01-03 22:36:26 +02:00
try:
2023-03-09 17:25:06 +02:00
if entry["user"] not in jsonLoad(
path.join(configGet("cache", "locations"), "group_members")
):
2023-01-16 13:09:53 +02:00
continue
2023-01-03 22:36:26 +02:00
tg_user = await app.get_users(entry["user"])
2023-03-09 17:25:06 +02:00
await app.send_message(configGet("admin", "groups"), locale("birthday", "message").format(str(tg_user.first_name), str(tg_user.username), str(relativedelta(datetime.now(), entry["application"]["2"], "%d.%m.%Y").years))) # type: ignore
2023-01-03 22:36:26 +02:00
logWrite(f"Notified admins about {entry['user']}'s birthday")
except Exception as exp:
2023-03-09 17:25:06 +02:00
logWrite(
f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'"
)
2023-01-03 22:36:26 +02:00
continue
logWrite("Birthdays check performed")
2022-12-10 16:52:34 +02:00
2022-12-18 00:36:39 +02:00
# Check for expired sponsorships
2023-01-03 22:36:26 +02:00
if configGet("enabled", "features", "sponsorships") is True:
if configGet("enabled", "scheduler", "sponsorships") is True:
2023-03-09 17:25:06 +02:00
@scheduler.scheduled_job(
trigger="cron", hour=configGet("time", "scheduler", "sponsorships")
)
2023-01-03 22:36:26 +02:00
async def check_sponsors():
2023-03-09 17:25:06 +02:00
for entry in col_sponsorships.find(
{"sponsorship.expires": {"$lt": datetime.now() + timedelta(days=2)}}
):
2022-12-22 16:05:27 +02:00
try:
2023-03-09 17:25:06 +02:00
if entry["user"] not in jsonLoad(
path.join(configGet("cache", "locations"), "group_members")
):
2023-01-16 13:09:53 +02:00
continue
2022-12-22 16:05:27 +02:00
tg_user = await app.get_users(entry["user"])
2023-03-09 17:25:06 +02:00
until_expiry = (
abs(
relativedelta(
datetime.now(), entry["sponsorship"]["expires"]
).days
)
+ 1
)
await app.send_message(tg_user.id, locale("sponsorships_expires", "message").format(until_expiry)) # type: ignore
logWrite(
f"Notified user {entry['user']} that sponsorship expires in {until_expiry} days"
)
2023-01-03 22:36:26 +02:00
except Exception as exp:
2023-03-09 17:25:06 +02:00
logWrite(
f"Could not find user {entry['user']} notify about sponsorship expiry due to '{exp}'"
)
2023-01-03 22:36:26 +02:00
continue
2023-03-09 17:25:06 +02:00
for entry in col_sponsorships.find(
{"sponsorship.expires": {"$lt": datetime.now() - timedelta(days=1)}}
):
2023-01-03 22:36:26 +02:00
try:
holo_user = HoloUser(entry["user"])
2023-01-16 13:09:53 +02:00
col_sponsorships.find_one_and_delete({"user": holo_user.id})
2023-03-09 17:25:06 +02:00
if entry["user"] not in jsonLoad(
path.join(configGet("cache", "locations"), "group_members")
):
2023-01-16 13:09:53 +02:00
continue
2023-03-09 17:25:06 +02:00
await app.send_message(entry["user"], locale("sponsorships_expired", "message")) # type: ignore
2023-01-04 20:59:09 +02:00
await holo_user.label_reset(configGet("users", "groups"))
2023-01-03 22:36:26 +02:00
try:
tg_user = await app.get_users(entry["user"])
2023-03-09 17:25:06 +02:00
logWrite(
f"Notified user {entry['user']} that sponsorship expired"
)
2023-01-03 22:36:26 +02:00
except Exception as exp:
2023-03-09 17:25:06 +02:00
logWrite(
f"Could not find user {entry['user']} notify about sponsorship expired due to '{exp}'"
)
2022-12-22 16:05:27 +02:00
except Exception as exp:
2023-03-09 17:25:06 +02:00
logWrite(
f"Could not reset label of user {entry['user']} due to '{exp}'"
)
2023-01-03 22:36:26 +02:00
continue
logWrite("Sponsorships check performed")
2022-12-18 00:36:39 +02:00
2023-04-02 17:44:46 +03:00
# Revoke old warnings
if configGet("enabled", "features", "warnings") is True:
if configGet("enabled", "scheduler", "warnings_revocation") is True:
@scheduler.scheduled_job(
trigger="date", run_date=datetime.now() + timedelta(seconds=10)
)
@scheduler.scheduled_job(
trigger="interval",
hours=configGet("interval", "scheduler", "warnings_revocation"),
)
async def revoke_warnings():
for warning in list(
col_warnings.find(
{
"active": True,
"date": {"$lt": datetime.now() - timedelta(days=90)},
}
)
):
if (
col_warnings.count_documents(
{
"user": warning["user"],
"active": True,
"date": {"$gt": datetime.now() - timedelta(days=90)},
}
)
== 0
):
col_warnings.update_one(
{"_id": warning["_id"]},
{"$set": {"active": False, "revoke_date": datetime.now()}},
)
logWrite(
f'Revoked warning {str(warning["_id"])} of user {warning["user"]} because no active warnings for the last 90 days found.'
)
await app.send_message(
configGet("admin", "groups"),
locale("warning_revoked_auto", "message").format(
warning["user"], warning["date"].strftime("%d.%m.%Y")
),
)
2023-04-02 17:44:46 +03:00
2022-12-18 00:36:39 +02:00
# Register all bot commands
2023-03-09 17:25:06 +02:00
@scheduler.scheduled_job(
trigger="date", run_date=datetime.now() + timedelta(seconds=10)
)
2022-12-18 00:36:39 +02:00
async def commands_register():
2023-01-03 22:36:26 +02:00
commands = {
"users": [],
"admins": [],
"owner": [],
2023-01-03 22:36:26 +02:00
"group_users": [],
"group_admins": [],
"group_users_admins": [],
2023-03-09 17:25:06 +02:00
"locales": {},
2023-01-03 22:36:26 +02:00
}
commands_raw = {
"users": [],
"admins": [],
"owner": [],
"group_users": [],
"group_admins": [],
"group_users_admins": [],
2023-03-09 17:25:06 +02:00
"locales": {},
}
2022-12-18 00:36:39 +02:00
valid_locales = []
files_locales = listdir(f'{configGet("locale", "locations")}')
2023-01-03 22:54:01 +02:00
2022-12-18 00:36:39 +02:00
for entry in files_locales:
if entry.endswith(".json"):
valid_locales.append(".".join(entry.split(".")[:-1]))
2023-01-03 22:36:26 +02:00
commands["locales"][".".join(entry.split(".")[:-1])] = {
"users": [],
"admins": [],
"owner": [],
2023-01-03 22:36:26 +02:00
"group_users": [],
"group_admins": [],
2023-03-09 17:25:06 +02:00
"group_users_admins": [],
2023-01-03 22:36:26 +02:00
}
if configGet("debug") is True:
commands_raw["locales"][".".join(entry.split(".")[:-1])] = {
"users": [],
"admins": [],
"owner": [],
"group_users": [],
"group_admins": [],
2023-03-09 17:25:06 +02:00
"group_users_admins": [],
}
2023-01-03 22:36:26 +02:00
config_modules = configGet("features")
config_commands = configGet("commands")
for command in config_commands:
enabled = False
for module in config_commands[command]["modules"]:
2023-01-03 22:54:01 +02:00
if config_modules[module]["enabled"] is True:
2023-01-03 22:36:26 +02:00
enabled = True
if enabled is False:
2023-01-09 13:39:39 +02:00
logWrite(f"Not registering {command} at all", debug=True)
2023-01-03 22:36:26 +02:00
continue
for permission in config_commands[command]["permissions"]:
2023-03-09 17:25:06 +02:00
commands[permission].append(
BotCommand(command, locale("commands")[command])
)
if configGet("debug") is True:
2023-03-09 17:25:06 +02:00
commands_raw[permission].append(
{f"{command}": locale("commands")[command]}
)
logWrite(f"Registering {command} for {permission}")
2023-01-03 22:36:26 +02:00
for lc in valid_locales:
2023-03-09 17:25:06 +02:00
commands["locales"][lc][permission].append(
BotCommand(command, locale("commands", locale=lc)[command])
)
2023-01-03 22:36:26 +02:00
if configGet("debug") is True:
2023-03-09 17:25:06 +02:00
commands_raw["locales"][lc][permission].append(
{f"{command}": locale("commands", locale=lc)[command]}
)
logWrite(f"Registering {command} for {permission} [{lc}]")
2022-12-18 00:36:39 +02:00
# Registering user commands
2023-01-03 22:36:26 +02:00
await app.set_bot_commands(commands["users"])
2022-12-18 00:36:39 +02:00
logWrite("Registered user commands for default locale")
# Registering user commands for each locale
for lc in valid_locales:
2023-01-03 22:36:26 +02:00
await app.set_bot_commands(commands["locales"][lc]["users"], language_code=lc)
2022-12-18 00:36:39 +02:00
logWrite(f"Registered user commands for locale {lc}")
# Registering admin commands
for admin in configGet("admins"):
2022-12-18 00:36:39 +02:00
try:
2023-03-09 17:25:06 +02:00
await app.set_bot_commands(
commands["admins"] + commands["users"],
scope=BotCommandScopeChat(chat_id=admin),
)
logWrite(f"Registered admin commands for admin {admin}")
2022-12-18 00:36:39 +02:00
except bad_request_400.PeerIdInvalid:
pass
# Registering owner commands
try:
2023-03-09 17:25:06 +02:00
await app.set_bot_commands(
commands["admins"] + commands["owner"] + commands["users"],
scope=BotCommandScopeChat(chat_id=configGet("owner")),
)
for lc in valid_locales:
2023-03-09 17:25:06 +02:00
await app.set_bot_commands(
commands["locales"][lc]["admins"]
+ commands["locales"][lc]["owner"]
+ commands["locales"][lc]["users"],
scope=BotCommandScopeChat(chat_id=configGet("owner")),
)
logWrite(f"Registered admin commands for owner {configGet('owner')}")
except bad_request_400.PeerIdInvalid:
pass
2022-12-18 00:36:39 +02:00
# Registering admin group commands
try:
2023-03-09 17:25:06 +02:00
await app.set_bot_commands(
commands["group_admins"],
scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")),
)
2022-12-18 00:36:39 +02:00
logWrite("Registered admin group commands for default locale")
except bad_request_400.ChannelInvalid:
2023-03-09 17:25:06 +02:00
logWrite(
f"Could not register commands for admin group. Bot is likely not in the group."
)
2022-12-18 00:36:39 +02:00
# Registering destination group commands
try:
2023-03-09 17:25:06 +02:00
await app.set_bot_commands(
commands["group_users"],
scope=BotCommandScopeChat(chat_id=configGet("users", "groups")),
)
2022-12-18 00:36:39 +02:00
logWrite("Registered destination group commands")
except bad_request_400.ChannelInvalid:
2023-03-09 17:25:06 +02:00
logWrite(
f"Could not register commands for destination group. Bot is likely not in the group."
)
# Registering destination group admin commands
try:
2023-03-09 17:25:06 +02:00
await app.set_bot_commands(
commands["group_users_admins"],
scope=BotCommandScopeChatAdministrators(
chat_id=configGet("users", "groups")
),
)
logWrite("Registered destination group admin commands")
except bad_request_400.ChannelInvalid:
2023-03-09 17:25:06 +02:00
logWrite(
f"Could not register admin commands for destination group. Bot is likely not in the group."
)
if configGet("debug") is True:
2023-01-04 23:31:58 +02:00
print(commands, flush=True)
2023-03-09 17:25:06 +02:00
logWrite(
f"Complete commands registration:\n{dumps(commands_raw, indent=4, ensure_ascii=False, encode_html_chars=False)}",
debug=True,
)
if configGet("enabled", "scheduler", "channels_monitor"):
2023-03-09 17:25:06 +02:00
@scheduler.scheduled_job(
trigger="interval",
minutes=configGet("interval", "scheduler", "channels_monitor"),
)
async def channels_monitor():
for channel in configGet("channels", "scheduler", "channels_monitor"):
if configGet("debug") is True:
2023-03-09 17:25:06 +02:00
logWrite(
f'Processing videos of {channel["name"]} ({channel["id"]})',
debug=True,
)
try:
2023-03-09 17:25:06 +02:00
req = get(
f'https://www.youtube.com/feeds/videos.xml?channel_id={channel["id"]}'
)
parsed = parse(req.content)
if "feed" not in parsed:
continue
if "entry" not in parsed["feed"]:
continue
for entry in parsed["feed"]["entry"]:
if "yt:videoId" not in entry:
continue
2023-03-09 17:25:06 +02:00
if (
col_youtube.find_one(
{"channel": channel["id"], "video": entry["yt:videoId"]}
)
is None
):
col_youtube.insert_one(
{
"channel": channel["id"],
"video": entry["yt:videoId"],
"date": datetime.fromisoformat(entry["published"]),
}
)
await app.send_message(
configGet("users", "groups"),
locale("youtube_video", "message").format(
channel["name"],
channel["link"],
entry["title"],
entry["link"]["@href"],
),
disable_web_page_preview=False,
)
await sleep(2)
except Exception as exp:
2023-03-09 17:25:06 +02:00
logWrite(
f'Could not get last videos of {channel["name"]} ({channel["id"]}) due to {exp}: {format_exc()}'
)
if configGet("debug") is True:
2023-03-09 17:25:06 +02:00
logWrite("Admin group caching performed", debug=True)