7 Commits

17 changed files with 62 additions and 208 deletions

View File

@@ -51,8 +51,7 @@
"enabled": false "enabled": false
}, },
"spoilers": { "spoilers": {
"enabled": true, "enabled": true
"allow_external": true
} }
}, },
"scheduler": { "scheduler": {
@@ -75,11 +74,6 @@
"cache_admins": { "cache_admins": {
"interval": 120, "interval": 120,
"enabled": true "enabled": true
},
"channels_monitor": {
"interval": 5,
"enabled": true,
"channels": []
} }
}, },
"locations": { "locations": {

View File

@@ -31,7 +31,7 @@ from modules.commands.warnings import *
from modules.callbacks.nothing import * from modules.callbacks.nothing import *
from modules.callbacks.reapply import * from modules.callbacks.reapply import *
from modules.callbacks.rules import * from modules.callbacks.rules import *
from modules.callbacks.spoiler import * from modules.callbacks.sid import *
from modules.callbacks.sponsorship import * from modules.callbacks.sponsorship import *
from modules.callbacks.sub import * from modules.callbacks.sub import *
from modules.callbacks.sus import * from modules.callbacks.sus import *

View File

@@ -4,7 +4,7 @@
"goodbye": "Добре, дякуємо за чесність! Вибачте, але за таких умов ми не будемо тебе додавати до спільноти. Якщо передумаєш та захочеш приєднатись - просто натисни на кнопку.", "goodbye": "Добре, дякуємо за чесність! Вибачте, але за таких умов ми не будемо тебе додавати до спільноти. Якщо передумаєш та захочеш приєднатись - просто натисни на кнопку.",
"privacy_notice": "Раді це чути!\n\nДля продовження треба буде заповнити невеличку анкетку. Будь ласка, віднесись до цього серйозно. Ми відповідально ставимось до персональних даних, тому ця анкета не буде передана третім особам, а буде використана лише для проходження до спільноти.", "privacy_notice": "Раді це чути!\n\nДля продовження треба буде заповнити невеличку анкетку. Будь ласка, віднесись до цього серйозно. Ми відповідально ставимось до персональних даних, тому ця анкета не буде передана третім особам, а буде використана лише для проходження до спільноти.",
"question1": "Як до тебе можна звертатись?", "question1": "Як до тебе можна звертатись?",
"question2": "Коли в тебе день народження?\n\nБудь ласка, у форматі ДД.ММ.РРРР", "question2": "Коли в тебе день народження?",
"question3": "З якого ти міста або де проживаєш зараз?\n\n⚠ Будь ласка, не вказуйте точних адрес! \"Київ\" або \"Київська Область\" є достатньою конкретизацією.\n\nПриклади:\n• Київ\n• Одеська область\n• Макіївка (Луганська область)", "question3": "З якого ти міста або де проживаєш зараз?\n\n⚠ Будь ласка, не вказуйте точних адрес! \"Київ\" або \"Київська Область\" є достатньою конкретизацією.\n\nПриклади:\n• Київ\n• Одеська область\n• Макіївка (Луганська область)",
"question4": "Коли вперше довелось дізнатись про Хололайв?", "question4": "Коли вперше довелось дізнатись про Хололайв?",
"question5": "Чим тебе зацікавив Хололайв?", "question5": "Чим тебе зацікавив Хололайв?",
@@ -109,9 +109,7 @@
"spoiler_unfinished": "У вас ще є незавершений спойлер. Надішліть /cancel щоб зупинити його створення", "spoiler_unfinished": "У вас ще є незавершений спойлер. Надішліть /cancel щоб зупинити його створення",
"spoiler_cancel": "Створення спойлера було припинено", "spoiler_cancel": "Створення спойлера було припинено",
"spoiler_empty": "Спойлер категорії \"{0}\" без опису", "spoiler_empty": "Спойлер категорії \"{0}\" без опису",
"spoiler_empty_named": "Спойлер категорії \"{0}\" без опису від **{1}**",
"spoiler_described": "Спойлер категорії \"{0}\": {1}", "spoiler_described": "Спойлер категорії \"{0}\": {1}",
"spoiler_described_named": "Спойлер категорії \"{0}\" від **{1}**: {2}",
"spoiler_description_enter": "Добре, введіть бажаний опис спойлера", "spoiler_description_enter": "Добре, введіть бажаний опис спойлера",
"spoiler_description_too_long": "Текст занадто довгий. Будь ласка, умісти опис у 1024 символи.", "spoiler_description_too_long": "Текст занадто довгий. Будь ласка, умісти опис у 1024 символи.",
"spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)", "spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)",
@@ -120,7 +118,6 @@
"spoiler_incorrect_content": "Бот не підтримує такий контент. Будь ласка, надішли текст, фото, відео, файл або анімацію (гіф).", "spoiler_incorrect_content": "Бот не підтримує такий контент. Будь ласка, надішли текст, фото, відео, файл або анімацію (гіф).",
"spoiler_incorrect_category": "Вказана категорія не є дійсною. Будь ласка, користуйся клавіатурою бота (кнопка біля 📎) для вибору категорії.", "spoiler_incorrect_category": "Вказана категорія не є дійсною. Будь ласка, користуйся клавіатурою бота (кнопка біля 📎) для вибору категорії.",
"spoiler_in_progress": "❌ **Дія неможлива**\nПерш ніж починати нову дію, треба завершити створення спойлера або перервати його командою /cancel.", "spoiler_in_progress": "❌ **Дія неможлива**\nПерш ніж починати нову дію, треба завершити створення спойлера або перервати його командою /cancel.",
"youtube_video": "На каналі [{0}]({1}) нове відео!\n\n**[{2}]({3})**",
"yes": "Так", "yes": "Так",
"no": "Ні", "no": "Ні",
"voice_message": [ "voice_message": [
@@ -229,10 +226,8 @@
"done": "✅ Готово", "done": "✅ Готово",
"sponsor_apply": "Заповнити форму", "sponsor_apply": "Заповнити форму",
"sponsor_started": "Форму розпочато", "sponsor_started": "Форму розпочато",
"spoiler_view": "Переглянути", "spoiler_send": "Надіслати",
"spoiler_preview": опередній перегляд", "spoiler_view": ереглянути"
"spoiler_send_chat": "Надіслати в холо-чат",
"spoiler_send_other": "Надіслати в інший чат"
}, },
"callback": { "callback": {
"sub_accepted": "✅ Анкету {0} схвалено", "sub_accepted": "✅ Анкету {0} схвалено",
@@ -248,8 +243,7 @@
"reapply_stopped": " Перервано заповнення анкети", "reapply_stopped": " Перервано заповнення анкети",
"sponsor_started": " Заповнення форми розпочато", "sponsor_started": " Заповнення форми розпочато",
"sponsor_accepted": "✅ Форму {0} схвалено", "sponsor_accepted": "✅ Форму {0} схвалено",
"sponsor_rejected": "❌ Форму {0} відхилено", "sponsor_rejected": "❌ Форму {0} відхилено"
"spoiler_sent": "✅ Повідомлення надіслано в холо-чат"
}, },
"inline": { "inline": {
"forbidden": { "forbidden": {

View File

@@ -83,30 +83,13 @@ async def callback_query_reapply_reject(app: Client, clb: CallbackQuery):
# Use old application when user reapplies after leaving the chat # Use old application when user reapplies after leaving the chat
@app.on_callback_query(filters.regex("reapply_old_[\s\S]*")) @app.on_callback_query(filters.regex("reapply_old_[\s\S]*"))
async def callback_query_reapply_old(app: Client, clb: CallbackQuery): async def callback_query_reapply_old(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(clb.from_user)
if holo_user.sponsorship_state()[0] == "fill": if HoloUser(clb.from_user).sponsorship_state()[0] == "fill":
await clb.message.reply_text(locale("finish_sponsorship", "message"), quote=False) await clb.message.reply_text(locale("finish_sponsorship", "message"), quote=False)
return return
message = await app.get_messages(clb.from_user.id, int(fullclb[2])) message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
if col_tmp.find_one({"user": holo_user.id, "type": "application"}) is None and col_applications.find_one({"user": holo_user.id}) is not None:
col_tmp.insert_one(
{
"user": holo_user.id,
"type": "application",
"complete": True,
"sent": False,
"state": "fill",
"reapply": True,
"stage": 10,
"application": col_applications.find_one({"user": holo_user.id})["application"]
}
)
await confirm_yes(app, message, kind="application") await confirm_yes(app, message, kind="application")
await clb.message.edit(clb.message.text, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("done", "button", locale=clb.from_user), "nothing")]])) await clb.message.edit(clb.message.text, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("done", "button", locale=clb.from_user), "nothing")]]))

10
modules/callbacks/sid.py Normal file
View File

@@ -0,0 +1,10 @@
from app import app
from pyrogram.types import CallbackQuery
from pyrogram.client import Client
from pyrogram import filters
# Callback rule ================================================================================================================
@app.on_callback_query(filters.regex("sid_[\s\S]*"))
async def callback_query_rule(app: Client, clb: CallbackQuery):
await clb.answer(url=f'https://t.me/{(await app.get_me()).username}?start={clb.data.split("_")[1]}')
# ==============================================================================================================================

View File

@@ -1,31 +0,0 @@
from app import app
from pyrogram.types import CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
from pyrogram.client import Client
from pyrogram import filters
from modules.database import col_spoilers
from bson.objectid import ObjectId
from modules.utils import configGet, locale
# Callback sid =================================================================================================================
@app.on_callback_query(filters.regex("sid_[\s\S]*"))
async def callback_query_sid(app: Client, clb: CallbackQuery):
await clb.answer(url=f'https://t.me/{(await app.get_me()).username}?start={clb.data.split("_")[1]}')
# ==============================================================================================================================
# Callback shc =================================================================================================================
@app.on_callback_query(filters.regex("shc_[\s\S]*"))
async def callback_query_shc(app: Client, clb: CallbackQuery):
spoil = col_spoilers.find_one( {"_id": ObjectId(clb.data.split("_")[1])} )
if spoil["description"] == "":
desc = locale("spoiler_empty_named", "message", locale=clb.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), clb.from_user.first_name)
else:
desc = locale("spoiler_described_named", "message", locale=clb.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), clb.from_user.first_name, spoil["description"])
await app.send_message(configGet("users", "groups"), desc, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=clb.from_user), callback_data=f'sid_{clb.data.split("_")[1]}')]]))
await app.send_message(configGet("admin", "groups"), desc, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=clb.from_user), callback_data=f'sid_{clb.data.split("_")[1]}')]]))
await clb.answer(locale("spoiler_sent", "callback", locale=clb.from_user), show_alert=True)
# ==============================================================================================================================

View File

@@ -51,7 +51,7 @@ async def cmd_identify(app: Client, msg: Message):
if user.photo is not None: if user.photo is not None:
await app.send_chat_action(msg.chat.id, action=ChatAction.UPLOAD_PHOTO) await app.send_chat_action(msg.chat.id, action=ChatAction.UPLOAD_PHOTO)
await msg.reply_photo( await msg.reply_photo(
create_tmp((await download_tmp(app, user.photo.big_file_id))[1], kind="image"), create_tmp(await download_tmp(app, user.photo.big_file_id), kind="image"),
quote=should_quote(msg), quote=should_quote(msg),
caption=output caption=output
) )

View File

@@ -6,7 +6,7 @@ from classes.holo_user import HoloUser
from modules.logging import logWrite from modules.logging import logWrite
from modules.utils import configGet, locale, should_quote from modules.utils import configGet, locale, should_quote
from modules.handlers.welcome import welcome_pass from modules.handlers.welcome import welcome_pass
from modules.database import col_tmp, col_applications from modules.database import col_tmp
from modules import custom_filters from modules import custom_filters
# Reapply command ============================================================================================================== # Reapply command ==============================================================================================================
@@ -27,40 +27,27 @@ async def cmd_reapply(app: Client, msg: Message):
if member.user.id == msg.from_user.id: if member.user.id == msg.from_user.id:
left_chat = False left_chat = False
if left_chat is True: if not left_chat:
if holo_user.sponsorship_state()[0] == "fill":
if (holo_user.application_state()[1] is True and holo_user.application_state()[0] != "fill"): await msg.reply_text(locale("finish_sponsorship", "message"), quote=should_quote(msg))
return
await msg.reply_text(locale("reapply_left_chat", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup([
[
InlineKeyboardButton(locale("reapply_old_one", "button", locale=holo_user), f"reapply_old_{msg.id}")
],
[
InlineKeyboardButton(locale("reapply_new_one", "button", locale=holo_user), f"reapply_new_{msg.id}")
]
]))
elif col_tmp.find_one({"user": holo_user.id, "type": "application"}) is None and col_applications.find_one({"user": holo_user.id}) is not None:
await msg.reply_text(locale("reapply_left_chat", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup([
[
InlineKeyboardButton(locale("reapply_old_one", "button", locale=holo_user), f"reapply_old_{msg.id}")
],
[
InlineKeyboardButton(locale("reapply_new_one", "button", locale=holo_user), f"reapply_new_{msg.id}")
]
]))
else:
holo_user.application_restart(reapply=True) holo_user.application_restart(reapply=True)
await welcome_pass(app, msg, once_again=True) await welcome_pass(app, msg, once_again=True)
else: else:
if holo_user.sponsorship_state()[0] == "fill": if holo_user.application_state()[1] is True and holo_user.application_state()[0] != "fill":
await msg.reply_text(locale("finish_sponsorship", "message"), quote=should_quote(msg))
return await msg.reply_text(locale("reapply_left_chat", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup([
[
InlineKeyboardButton(locale("reapply_old_one", "button", locale=holo_user), f"reapply_old_{msg.id}")
],
[
InlineKeyboardButton(locale("reapply_new_one", "button", locale=holo_user), f"reapply_new_{msg.id}")
]
]))
else:
holo_user.application_restart(reapply=True) holo_user.application_restart(reapply=True)
await welcome_pass(app, msg, once_again=True) await welcome_pass(app, msg, once_again=True)

View File

@@ -10,7 +10,7 @@ from modules.database import col_spoilers
from modules import custom_filters from modules import custom_filters
# Spoiler command ============================================================================================================== # Spoiler command ==============================================================================================================
@app.on_message(custom_filters.enabled_spoilers & custom_filters.member & ~filters.scheduled & filters.private & filters.command(["spoiler"], prefixes=["/"])) @app.on_message(custom_filters.member & ~filters.scheduled & filters.private & filters.command(["spoiler"], prefixes=["/"]))
async def cmd_spoiler(app: Client, msg: Message): async def cmd_spoiler(app: Client, msg: Message):
try: try:

View File

@@ -39,9 +39,6 @@ async def enabled_invites_check_func(_, __, msg: Message):
async def enabled_dinovoice_func(_, __, msg: Message): async def enabled_dinovoice_func(_, __, msg: Message):
return configGet("enabled", "features", "dinovoice") return configGet("enabled", "features", "dinovoice")
async def enabled_spoilers_func(_, __, msg: Message):
return configGet("enabled", "features", "spoilers")
async def filling_sponsorship_func(_, __, msg: Message): async def filling_sponsorship_func(_, __, msg: Message):
return True if col_tmp.find_one({"user": msg.from_user.id, "type": "sponsorship"}) is not None else False return True if col_tmp.find_one({"user": msg.from_user.id, "type": "sponsorship"}) is not None else False
@@ -55,6 +52,5 @@ enabled_sponsorships = filters.create(enabled_sponsorships_func)
enabled_warnings = filters.create(enabled_warnings_func) enabled_warnings = filters.create(enabled_warnings_func)
enabled_invites_check = filters.create(enabled_invites_check_func) enabled_invites_check = filters.create(enabled_invites_check_func)
enabled_dinovoice = filters.create(enabled_dinovoice_func) enabled_dinovoice = filters.create(enabled_dinovoice_func)
enabled_spoilers = filters.create(enabled_spoilers_func)
filling_sponsorship = filters.create(filling_sponsorship_func) filling_sponsorship = filters.create(filling_sponsorship_func)

View File

@@ -28,14 +28,13 @@ db = db_client.get_database(name=db_config["name"])
collections = db.list_collection_names() collections = db.list_collection_names()
for collection in ["tmp", "users", "context", "youtube", "spoilers", "messages", "warnings", "applications", "sponsorships"]: for collection in ["tmp", "users", "context", "spoilers", "messages", "warnings", "applications", "sponsorships"]:
if not collection in collections: if not collection in collections:
db.create_collection(collection) db.create_collection(collection)
col_tmp = db.get_collection("tmp") col_tmp = db.get_collection("tmp")
col_users = db.get_collection("users") col_users = db.get_collection("users")
col_context = db.get_collection("context") col_context = db.get_collection("context")
col_youtube = db.get_collection("youtube")
col_spoilers = db.get_collection("spoilers") col_spoilers = db.get_collection("spoilers")
col_messages = db.get_collection("messages") col_messages = db.get_collection("messages")
col_warnings = db.get_collection("warnings") col_warnings = db.get_collection("warnings")

View File

@@ -22,7 +22,7 @@ async def message_context(msg: Message) -> tuple:
return 0, 0 return 0, 0
# Any other input ============================================================================================================== # Any other input ==============================================================================================================
@app.on_message(~ filters.scheduled & (filters.private | filters.chat(configGet("admin", "groups")))) @app.on_message(~ filters.scheduled & filters.private)
async def any_stage(app: Client, msg: Message): async def any_stage(app: Client, msg: Message):
if msg.via_bot is None: if msg.via_bot is None:
@@ -52,9 +52,6 @@ async def any_stage(app: Client, msg: Message):
return return
if msg.chat.id == configGet("admin", "groups"):
return
if msg.text is not None: if msg.text is not None:
if configGet("enabled", "features", "applications") is True: if configGet("enabled", "features", "applications") is True:
@@ -69,9 +66,6 @@ async def any_stage(app: Client, msg: Message):
if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill": if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill":
if configGet("enabled", "features", "spoilers") is False:
return
spoiler = col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} ) spoiler = col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} )
if spoiler is None: if spoiler is None:
@@ -152,37 +146,7 @@ async def any_stage(app: Client, msg: Message):
ready = True ready = True
if ready is True: if ready is True:
if configGet("allow_external", "features", "spoilers") is True: await msg.reply_text(locale("spoiler_ready", "message", locale=msg.from_user), reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_send", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")]]))
await msg.reply_text(
locale("spoiler_ready", "message", locale=msg.from_user),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("spoiler_preview", "button", locale=msg.from_user), callback_data=f"sid_{spoiler['_id'].__str__()}")
],
[
InlineKeyboardButton(locale("spoiler_send_chat", "button", locale=msg.from_user), callback_data=f"shc_{spoiler['_id'].__str__()}")
],
[
InlineKeyboardButton(locale("spoiler_send_other", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")
]
]
)
)
else:
await msg.reply_text(
locale("spoiler_ready", "message", locale=msg.from_user),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("spoiler_preview", "button", locale=msg.from_user), callback_data=f"sid_{spoiler['_id'].__str__()}")
],
[
InlineKeyboardButton(locale("spoiler_send_chat", "button", locale=msg.from_user), callback_data=f"shc_{spoiler['_id'].__str__()}")
]
]
)
)
else: else:
await msg.reply_text(locale("spoiler_incorrect_content", "message", locale=msg.from_user)) await msg.reply_text(locale("spoiler_incorrect_content", "message", locale=msg.from_user))

View File

@@ -30,10 +30,7 @@ async def welcome_pass(app: Client, msg: Message, once_again: bool = False) -> N
if once_again is False: if once_again is False:
holo_user.application_restart() holo_user.application_restart()
if once_again is True:
logWrite(f"User {msg.from_user.id} confirmed starting the application") logWrite(f"User {msg.from_user.id} confirmed starting the application")
else:
logWrite(f"User {msg.from_user.id} confirmed starting the application once again")
await msg.reply_text(locale("question1", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("question1", "force_reply", locale=msg.from_user))) await msg.reply_text(locale("question1", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("question1", "force_reply", locale=msg.from_user)))
welcome_2 = [] welcome_2 = []

View File

@@ -22,8 +22,6 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
results = [] results = []
if configGet("allow_external", "features", "spoilers") is True:
if inline_query.query.startswith("spoiler:"): if inline_query.query.startswith("spoiler:"):
try: try:

View File

@@ -1,9 +1,7 @@
"""Automatically register commands and execute """Automatically register commands and execute
some scheduled tasks is the main idea of this module""" some scheduled tasks is the main idea of this module"""
from asyncio import sleep
from os import listdir, makedirs, path, sep from os import listdir, makedirs, path, sep
from traceback import format_exc
from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.schedulers.asyncio import AsyncIOScheduler
from datetime import datetime, timedelta from datetime import datetime, timedelta
from ujson import dumps from ujson import dumps
@@ -12,11 +10,9 @@ from pyrogram.types import BotCommand, BotCommandScopeChat, BotCommandScopeChatA
from pyrogram.errors import bad_request_400 from pyrogram.errors import bad_request_400
from pyrogram.enums.chat_members_filter import ChatMembersFilter from pyrogram.enums.chat_members_filter import ChatMembersFilter
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
from modules.utils import configGet, jsonLoad, jsonSave, locale, logWrite from modules.utils import configGet, jsonSave, locale, logWrite
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from modules.database import col_applications, col_sponsorships, col_youtube from modules.database import col_applications, col_sponsorships
from xmltodict import parse
from requests import get
scheduler = AsyncIOScheduler() scheduler = AsyncIOScheduler()
@@ -66,8 +62,6 @@ if configGet("enabled", "features", "applications") is True:
for entry in col_applications.find(): for entry in col_applications.find():
if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"): if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"):
try: try:
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
continue
tg_user = await app.get_users(entry["user"]) tg_user = await app.get_users(entry["user"])
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 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
logWrite(f"Notified admins about {entry['user']}'s birthday") logWrite(f"Notified admins about {entry['user']}'s birthday")
@@ -84,8 +78,6 @@ if configGet("enabled", "features", "sponsorships") is True:
async def check_sponsors(): async def check_sponsors():
for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()+timedelta(days=2)}}): for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()+timedelta(days=2)}}):
try: try:
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
continue
tg_user = await app.get_users(entry["user"]) tg_user = await app.get_users(entry["user"])
until_expiry = relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days until_expiry = relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days
await app.send_message( tg_user.id, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore await app.send_message( tg_user.id, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore
@@ -96,11 +88,9 @@ if configGet("enabled", "features", "sponsorships") is True:
for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()}}): for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()}}):
try: try:
holo_user = HoloUser(entry["user"]) holo_user = HoloUser(entry["user"])
col_sponsorships.find_one_and_delete({"user": holo_user.id})
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
continue
await app.send_message( entry["user"], locale("sponsorships_expired", "message") ) # type: ignore await app.send_message( entry["user"], locale("sponsorships_expired", "message") ) # type: ignore
await holo_user.label_reset(configGet("users", "groups")) await holo_user.label_reset(configGet("users", "groups"))
col_sponsorships.find_one_and_delete({"user": holo_user.id})
try: try:
tg_user = await app.get_users(entry["user"]) tg_user = await app.get_users(entry["user"])
logWrite(f"Notified user that sponsorship expired") logWrite(f"Notified user that sponsorship expired")
@@ -244,29 +234,3 @@ async def commands_register():
if configGet("debug") is True: if configGet("debug") is True:
print(commands, flush=True) print(commands, flush=True)
logWrite(f"Complete commands registration:\n{dumps(commands_raw, indent=4, ensure_ascii=False, encode_html_chars=False)}", debug=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)

View File

@@ -1,4 +1,4 @@
from typing import Any, Literal, Tuple, Union from typing import Any, Literal, Union
from uuid import uuid1 from uuid import uuid1
from requests import get from requests import get
from pyrogram.enums.chat_type import ChatType from pyrogram.enums.chat_type import ChatType
@@ -212,7 +212,7 @@ def create_tmp(bytedata: Union[bytes, bytearray], kind: Union[Literal["image", "
file.write(bytedata) file.write(bytedata)
return path.join("tmp", filename) return path.join("tmp", filename)
async def download_tmp(app: Client, file_id: str) -> Tuple[str, bytes]: async def download_tmp(app: Client, file_id: str) -> bytes:
"""Download file by its ID and return its bytes """Download file by its ID and return its bytes
### Args: ### Args:
@@ -220,14 +220,14 @@ async def download_tmp(app: Client, file_id: str) -> Tuple[str, bytes]:
* file_id (`str`): File's unique id * file_id (`str`): File's unique id
### Returns: ### Returns:
* `Tuple[str, bytes]`: First is a filepath and the second is file's bytes * `bytes`: Bytes of downloaded file
""" """
filename = str(uuid1()) filename = str(uuid1())
makedirs("tmp", exist_ok=True) makedirs("tmp", exist_ok=True)
await app.download_media(file_id, path.join("tmp", filename)) await app.download_media(file_id, path.join("tmp", filename))
with open(path.join("tmp", filename), "rb") as f: with open(path.join("tmp", filename), "rb") as f:
bytedata = f.read() bytedata = f.read()
return path.join("tmp", filename), bytedata return bytedata
try: try:
from psutil import Process from psutil import Process

View File

@@ -9,4 +9,3 @@ python_dateutil==2.8.2
starlette~=0.22.0 starlette~=0.22.0
ujson~=5.7.0 ujson~=5.7.0
ftfy~=6.1.1 ftfy~=6.1.1
xmltodict~=0.13.0