Telegram/modules/scheduled.py

272 lines
13 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
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
from modules.database import col_applications, col_sponsorships, col_youtube
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"):
@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-01-04 14:31:42 +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
if configGet("enabled", "scheduler", "cache_admins"):
@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
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-01-09 15:43:19 +02:00
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=15))
2022-12-18 00:25:53 +02:00
@scheduler.scheduled_job(trigger="interval", hours=configGet("interval", "scheduler", "cache_avatars"))
async def cache_avatars():
list_of_users = []
2023-01-04 20:59:09 +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:
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)
2023-01-04 14:31:42 +02:00
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:
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "birthdays"))
async def check_birthdays():
for entry in col_applications.find():
if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"):
try:
2023-01-16 13:09:53 +02:00
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
continue
2023-01-03 22:36:26 +02:00
tg_user = await app.get_users(entry["user"])
2023-01-04 20:14:02 +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:
logWrite(f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'")
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:
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "sponsorships"))
async def check_sponsors():
for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()+timedelta(days=2)}}):
2022-12-22 16:05:27 +02:00
try:
2023-01-16 13:09:53 +02:00
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
continue
2022-12-22 16:05:27 +02:00
tg_user = await app.get_users(entry["user"])
2023-01-23 12:10: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
2023-01-23 12:10:06 +02:00
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:
logWrite(f"Could not find user {entry['user']} notify about sponsorship expiry due to '{exp}'")
continue
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})
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
continue
2023-01-03 22:36:26 +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-01-23 12:10:06 +02:00
logWrite(f"Notified user {entry['user']} that sponsorship expired")
2023-01-03 22:36:26 +02:00
except Exception as exp:
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-01-03 22:36:26 +02:00
logWrite(f"Could not reset label of user {entry['user']} due to '{exp}'")
continue
logWrite("Sponsorships check performed")
2022-12-18 00:36:39 +02:00
# Register all bot commands
2023-01-09 15:43:19 +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-01-03 22:36:26 +02:00
"locales": {}
}
commands_raw = {
"users": [],
"admins": [],
"owner": [],
"group_users": [],
"group_admins": [],
"group_users_admins": [],
"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": [],
"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": [],
"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-01-03 22:36:26 +02:00
commands[permission].append(BotCommand(command, locale("commands")[command]))
if configGet("debug") is True:
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-01-03 22:36:26 +02:00
commands["locales"][lc][permission].append(BotCommand(command, locale("commands", locale=lc)[command]))
if configGet("debug") is True:
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:
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:
await app.set_bot_commands(commands["admins"]+commands["owner"]+commands["users"], scope=BotCommandScopeChat(chat_id=configGet("owner")))
for lc in valid_locales:
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-01-04 20:14:02 +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:
logWrite(f"Could not register commands for admin group. Bot is likely not in the group.")
# Registering destination group commands
try:
2023-01-04 20:59:09 +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:
logWrite(f"Could not register commands for destination group. Bot is likely not in the group.")
# Registering destination group admin commands
try:
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:
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)
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"):
@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:
logWrite(f'Processing videos of {channel["name"]} ({channel["id"]})', debug=True)
try:
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
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:
logWrite(f'Could not get last videos of {channel["name"]} ({channel["id"]}) due to {exp}: {format_exc()}')
if configGet("debug") is True:
logWrite("Admin group caching performed", debug=True)