diff --git a/classes/holo_user.py b/classes/holo_user.py index 7454141..eeba107 100644 --- a/classes/holo_user.py +++ b/classes/holo_user.py @@ -1,4 +1,6 @@ from datetime import datetime +from os import sep +from uuid import uuid1 from requests import get from traceback import print_exc from app import app, isAnAdmin @@ -35,6 +37,24 @@ class DefaultApplicationTemp(dict): } } +class DefaultSponsorshipTemp(dict): + def __init__(self, user: int): + super().__init__({}) + self.dict = { + "user": user, + "type": "sponsorship", + "complete": False, + "sent": False, + "state": "fill", + "stage": 1, + "sponsorship": { + "streamer": None, + "expires": datetime.fromtimestamp(0), + "proof": None, + "label": "" + } + } + class UserNotFoundError(Exception): """HoloUser could not find user with such an ID in database""" def __init__(self, user, user_id): @@ -103,18 +123,18 @@ class HoloUser(): if isinstance(user, User): if (self.name != user.first_name) and hasattr(user, "first_name") and (user.first_name is not None): - self.set("tg_name", user.first_name) + self.set("name", user.first_name, db_key="tg_name") - if (self.phone != user.phone_number) and hasattr(user, "phone_number") and (user.phone_number is not None): - self.set("tg_phone", user.phone_number) + if (self.phone != user.phone_number) and hasattr(user, "phone") and (user.phone_number is not None): + self.set("phone", user.phone_number, db_key="tg_phone") - if (self.locale != user.language_code) and hasattr(user, "language_code") and (user.language_code is not None): - self.set("tg_locale", user.language_code) + if (self.locale != user.language_code) and hasattr(user, "locale") and (user.language_code is not None): + self.set("locale", user.language_code, db_key="tg_locale") if (self.username != user.username) and hasattr(user, "username") and (user.username is not None): - self.set("tg_username", user.username) + self.set("username", user.username, db_key="tg_username") - def set(self, key: str, value: Any) -> None: + def set(self, key: str, value: Any, db_key: Union[str, None] = None) -> None: """Set attribute data and save it into database ### Args: @@ -124,7 +144,8 @@ class HoloUser(): if not hasattr(self, key): raise AttributeError() setattr(self, key, value) - col_users.update_one(filter={"_id": self.db_id}, update={ "$set": { key: value } }, upsert=True) + db_key = key if db_key is None else db_key + col_users.update_one(filter={"_id": self.db_id}, update={ "$set": { db_key: value } }, upsert=True) logWrite(f"Set attribute {key} of user {self.id} to {value}") async def message(self, @@ -394,4 +415,97 @@ class HoloUser(): logWrite(f"User {self.id} completed stage {stage} of application") else: - return \ No newline at end of file + return + + def sponsorship_state(self) -> tuple[Literal["none", "fill", "approved", "rejected"], bool]: + """Check the current state of sponsorship in tmp collection + + ### Returns: + * `tuple[Literal["none", "fill", "approved", "rejected"], bool]`: First element is an enum of a state and the second one is whether sponsorship application is complete. + """ + tmp_sponsorship = col_tmp.find_one({"user": self.id, "type": "sponsorship"}) + if tmp_sponsorship is None: + return "none", False + else: + return tmp_sponsorship["state"], tmp_sponsorship["complete"] + + def sponsorship_valid(self) -> bool: + """Check whether user has a valid sponsorship + + ### Returns: + * `bool`: `True` if yes and `False` if no + """ + return True if col_sponsorships.find_one({"user": self.id, "expires": {"$gt": datetime.now()}}) is not None else False + + def sponsorship_restart(self) -> None: + """Reset sponsorship of a user in tmp collection and replace it with an empty one + """ + if col_tmp.find_one({"user": self.id, "type": "sponsorship"}) is None: + col_tmp.insert_one(document=DefaultSponsorshipTemp(self.id).dict) + else: + col_tmp.delete_one({"user": self.id, "type": "sponsorship"}) + col_tmp.insert_one(document=DefaultSponsorshipTemp(self.id).dict) + + async def sponsorship_next(self, query: str, msg: Message, photo: Union[Photo, None] = None) -> None: + """Move on filling sponsorship of user + + ### Args: + * query (`str`): Some kind of input + * msg (`Message`): Message that should receive replies + """ + + if col_tmp.find_one({"user": self.id, "type": "sponsorship"}) is not None: + + progress = col_tmp.find_one({"user": self.id, "type": "sponsorship"}) + stage = progress["stage"] + + if progress["state"] == "fill": + + if stage == 1: + + progress["sponsorship"]["streamer"] = query + col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}}) + await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale)))) + + elif stage == 2: + + try: + input_dt = datetime.strptime(query, "%d.%m.%Y") + except ValueError: + logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format") + await msg.reply_text(locale(f"sponsor2_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage}", "force_reply", locale=self.locale)))) + return + + if datetime.now() >= input_dt: + logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending date in the past") + await msg.reply_text(locale("sponsor2_past", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale("sponsor2", "force_reply", locale=self.locale)))) + return + + else: + progress["sponsorship"]["expires"] = input_dt + col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}}) + await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale)))) + + elif stage == 3: + + if photo is not None: + filename = uuid1() + await app.download_media(photo.file_id, f"tmp{sep}{filename}") + with open(f"tmp{sep}{filename}", "rb") as f: + photo_bytes = f.read() + progress["sponsorship"]["proof"] = photo_bytes + col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}}) + await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale)))) + + elif stage == 4: + progress["sponsorship"]["label"] = query + col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "complete": True}}) + await msg.reply_text("Sponsorship application is filled. Want to send it?", reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard", locale=self.locale), resize_keyboard=True)) + + else: + return + + logWrite(f"User {self.id} completed stage {stage} of sponsorship") + + else: + return \ No newline at end of file diff --git a/locale/uk.json b/locale/uk.json index 7ecc50d..1a4e63c 100644 --- a/locale/uk.json +++ b/locale/uk.json @@ -24,12 +24,16 @@ "sponsor1": "На яку саме дівчину платна підписка?", "sponsor2": "До якої дати (`ДД.ММ.РРРР`) підписка?", "sponsor2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`", + "sponsor2_past": "Вказана дата знаходиться в минулому. Будь ласка, вкажіть правильний термін дії підписки", "sponsor3": "Будь ласка, надішли одне фото для підтвердження дійсності підписки", + "sponsor4": "Яку роль ти бажаєш отримати?", "sponsorship_application_empty": "❌ **Дія неможлива**\nУ тебе немає заповненої та схваленої анкети. Заповни таку за допомогою /reapply та спробуй ще раз після її підтвердження.", "confirm": "Супер, дякуємо!\n\nБудь ласка, перевір правильність даних:\n{0}\n\nВсе правильно?", "application_sent": "Дякуємо! Ми надіслали твою анкетку на перевірку. Ти отримаєш повідомлення як тільки її перевірять та приймуть рішення. До тих пір від тебе більше нічого не потребується. Гарного дня! :)", - "application_got": "Отримано анкету від `{0}`\n\nІм'я тг: `{1}`, `{2}`\nЮзернейм: @{3}\n\n**Дані анкети:**\n{4}", - "reapply_got": "Отримано змінити анкети від `{0}`\n\nІм'я тг: `{1}`, `{2}`\nЮзернейм: @{3}\n\n**Дані анкети:**\n{4}", + "sponsorship_sent": "Дякуємо! Ми надіслали форму на перевірку. Ти отримаєш повідомлення як тільки її перевірять та приймуть рішення. Гарного дня! :)", + "application_got": "Отримано анкету від `{0}`\n\nІм'я тг: `{1}`\nЮзернейм: @{2}\n\n**Дані анкети:**\n{3}", + "reapply_got": "Отримано оновлення анкети від `{0}`\n\nІм'я тг: `{1}`\nЮзернейм: @{2}\n\n**Дані анкети:**\n{3}", + "sponsor_got": "Отримано форму на спонсорство від `{0}`\n\nІм'я тг: `{1}`\nЮзернейм: @{2}\n\n**Дані форми:**\n{3}", "shutdown": "Вимкнення бота з підом `{0}`", "startup": "Запуск бота з підом `{0}`", "startup_downtime": "Запуск бота з підом `{0}` (лежав {1})", @@ -43,6 +47,10 @@ "rejected_by": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`.", "rejected_by_agr": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`, заборонивши вступ до спільноти.\nПричина: агресивна/токсична анкета.", "rejected_by_rus": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`, заборонивши вступ до спільноти.\nПричина: русня.", + "sponsor_approved": "Вітаємо! Твою форму переглянули та підтвердили її правильність. Коли термін дії наданої підписки буде добігати кінця - ми нагадаємо, що треба оновити дані аби й надалі отримувати плюшки в боті. Гарного дня!", + "sponsor_rejected": "Ой лишенько! Твою форму переглянули, однак не підтвердили її. Можливо, щось не так з датами, або ж бажана роль не може бути надана.\n\nТи можеш спробувати повторно заповнити форму командою /sponsorship", + "sponsor_approved_by": "✅ **Підписку схвалено**\nАдмін **{0}** переглянув та схвалив форму `{1}`.", + "sponsor_rejected_by": "❌ **Підписку відхилено**\nАдмін **{0}** переглянув та відхилив форму `{1}`.", "contact": "Анкета `{0}`\n\n**Дані анкети:**\n{1}\n\n{2}", "application_status_accepted": "Прийнята `{0}` від {1}", "application_status_rejected": "Відхилена `{0}` від {1}", @@ -77,6 +85,8 @@ "no_user_application": "Не знайдено користувачів за запитом **{0}**", "user_invalid": "Надісланий користувач не має завершеної анкети.", "joined_false_link": "Користувач **{0}** (`{1}`) приєднався до групи не за своїм посиланням", + "sponsorships_expires": "⚠️ **Нагадування**\nНадана платна підписка припинить діяти **за {0} д**. Будь ласка, оновіть дані про неї командою /sponsorship інакше роль буде втрачено!", + "sponsorships_expired": "⚠️ **Нагадування**\nТермін дії вказаної підписки сплив. Для повторного отримання ролі користуйся командою /sponsorship.", "voice_message": [ "why are u gae", "руки відірвало? пиши як людина", @@ -93,6 +103,11 @@ "question8": "Дивлюсь стріми:", "question9": "Подобаються пісні:", "question10": "Про себе:" + }, + "sponsor_titles": { + "question_streamer": "Стрімер:", + "question_expires": "Підписка до:", + "question_label": "Хоче роль:" } }, "keyboard": { @@ -131,13 +146,16 @@ "question10": "Трошки про себе", "sponsor1": "Ім'я дівчини", "sponsor2": "Дата до якої підписка", - "sponsor3": "Фото-підтвердження" + "sponsor3": "Фото-підтвердження", + "sponsor4": "Бажана роль" }, "button": { "sub_yes": "✅ Прийняти", "sub_no": "❌ Відхилити", "sub_aggressive": "🤡 Відхилити (Токс)", "sub_russian": "🇷🇺 Відхилити (Русак)", + "sponsor_yes": "✅ Прийняти", + "sponsor_no": "❌ Відхилити", "accepted": "✅ Прийнято", "declined": "❌ Відхилено", "join": "Приєднатись", diff --git a/modules/callbacks/reapply.py b/modules/callbacks/reapply.py index fe693ac..9d0f53c 100644 --- a/modules/callbacks/reapply.py +++ b/modules/callbacks/reapply.py @@ -77,7 +77,7 @@ async def callback_query_reapply_reject(app, clb): async def callback_query_reapply_old(app, clb): fullclb = clb.data.split("_") message = await app.get_messages(clb.from_user.id, int(fullclb[2])) - await confirm_yes(app, message) + 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")]])) # Start a new application when user reapplies after leaving the chat diff --git a/modules/callbacks/sponsorship.py b/modules/callbacks/sponsorship.py index c0e6a95..ad52f1f 100644 --- a/modules/callbacks/sponsorship.py +++ b/modules/callbacks/sponsorship.py @@ -1,10 +1,10 @@ from datetime import datetime from app import app -from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton +from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ForceReply from pyrogram import filters from classes.holo_user import HoloUser from modules.utils import configGet, locale, logWrite -from modules.database import col_tmp,col_sponsorships +from modules.database import col_tmp, col_sponsorships # Callbacks sponsorship ======================================================================================================== @app.on_callback_query(filters.regex("sponsor_apply_[\s\S]*")) @@ -15,24 +15,51 @@ async def callback_query_sponsor_apply(app, clb): logWrite(f"User {holo_user.id} applied for sponsorship") - col_tmp.insert_one( - { - "user": holo_user.id, - "type": "sponsorship", - "complete": False, - "sent": False, - "state": "fill", - "stage": 1, - "sponsorship": { - "streamer": None, - "expires": datetime.fromtimestamp(0), - "proof": None, - "label": "" - } - } - ) + holo_user.sponsorship_restart() edited_markup = [[InlineKeyboardButton(text=str(locale("sponsor_started", "button")), callback_data="nothing")]] await clb.message.edit(text=locale("sponsorship_apply", "message"), reply_markup=InlineKeyboardMarkup(edited_markup)) - await clb.answer(text=locale("sponsor_started", "callback").format(holo_user.id), show_alert=False) \ No newline at end of file + await app.send_message(holo_user.id, locale(f"sponsor1", "message", locale=holo_user.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale)))) + await clb.answer(text=locale("sponsor_started", "callback").format(holo_user.id), show_alert=False) + +@app.on_callback_query(filters.regex("sponsor_yes_[\s\S]*")) +async def callback_query_sponsor_yes(app, clb): + + fullclb = clb.data.split("_") + holo_user = HoloUser(int(fullclb[2])) + + await app.send_message(configGet("admin_group"), locale("sponsor_approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) + await app.send_message(holo_user.id, locale("sponsor_approved", "message", locale=holo_user)) + logWrite(f"User {holo_user.id} got approved by {clb.from_user.id}") + + if col_sponsorships.find_one({"user": holo_user.id}) is not None: + col_sponsorships.update_one({"date": {"$eq": datetime.now()}, "admin": {"$eq": clb.from_user.id}, "sponsorship": {"$eq": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}})["sponsorship"]}}) + else: + col_sponsorships.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "sponsorship": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}})["sponsorship"]}) + + col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"state": "approved", "sent": False}}) + + await holo_user.set_label(configGet("destination_group"), col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}})["sponsorship"]["label"]) + + edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]] + + await app.edit_message_caption(clb.message.chat.id, clb.message.id, caption=clb.message.caption, reply_markup=InlineKeyboardMarkup(edited_markup)) + await clb.answer(text=f"✅ Confirmed {fullclb[2]}", show_alert=False) + +@app.on_callback_query(filters.regex("sponsor_no_[\s\S]*")) +async def callback_query_sponsor_no(app, clb): + + fullclb = clb.data.split("_") + holo_user = HoloUser(int(fullclb[2])) + + await app.send_message(configGet("admin_group"), locale("sponsor_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) + await app.send_message(holo_user.id, locale("sponsor_rejected", "message", locale=holo_user)) + logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id}") + + col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"state": "rejected", "sent": False}}) + + edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]] + + await app.edit_message_caption(clb.message.chat.id, clb.message.id, caption=clb.message.caption, reply_markup=InlineKeyboardMarkup(edited_markup)) + await clb.answer(text=f"❌ Rejected {fullclb[2]}", show_alert=False) \ No newline at end of file diff --git a/modules/handlers/confirmation.py b/modules/handlers/confirmation.py index 207c6be..4cbdf55 100644 --- a/modules/handlers/confirmation.py +++ b/modules/handlers/confirmation.py @@ -1,8 +1,11 @@ +from os import remove, sep +from typing import Literal +from uuid import uuid1 from dateutil.relativedelta import relativedelta from datetime import datetime from app import app from pyrogram import filters -from pyrogram.types import ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton +from pyrogram.types import ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton, ForceReply from pyrogram.enums.parse_mode import ParseMode from classes.holo_user import HoloUser from modules.utils import all_locales, configGet, locale, logWrite @@ -14,13 +17,11 @@ confirmation_1 = [] for pattern in all_locales("confirm", "keyboard"): confirmation_1.append(pattern[0][0]) @app.on_message(~ filters.scheduled & filters.private & filters.command(confirmation_1, prefixes=[""])) -async def confirm_yes(app, msg): +async def confirm_yes(app, msg, kind: Literal["application", "sponsorship"] = "unknown"): holo_user = HoloUser(msg.from_user) - if (holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True): - - await msg.reply_text(locale("application_sent", "message"), reply_markup=ReplyKeyboardRemove()) + if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)): tmp_application = col_tmp.find_one({"user": holo_user.id, "type": "application"}) @@ -28,6 +29,11 @@ async def confirm_yes(app, msg): logWrite(f"Application of {holo_user.id} is nowhere to be found.") return + if tmp_application["sent"] is True: + return + + await msg.reply_text(locale("application_sent", "message"), reply_markup=ReplyKeyboardRemove()) + application_content = [] i = 1 @@ -47,7 +53,7 @@ async def confirm_yes(app, msg): i += 1 if tmp_application["reapply"]: - await app.send_message(chat_id=configGet("admin_group"), text=(locale("reapply_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.last_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup( + await app.send_message(chat_id=configGet("admin_group"), text=(locale("reapply_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup( [ [ InlineKeyboardButton(text=str(locale("reapply_yes", "button")), callback_data=f"reapply_yes_{holo_user.id}") @@ -59,7 +65,7 @@ async def confirm_yes(app, msg): ) ) else: - await app.send_message(chat_id=configGet("admin_group"), text=(locale("application_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.last_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup( + await app.send_message(chat_id=configGet("admin_group"), text=(locale("application_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup( [ [ InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}") @@ -81,19 +87,74 @@ async def confirm_yes(app, msg): col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"sent": True}}) + return + # configSet(["sent"], True, file=str(holo_user.id)) # configSet(["confirmed"], True, file=str(holo_user.id)) + if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)): + + tmp_sponsorship = col_tmp.find_one({"user": holo_user.id, "type": "sponsorship"}) + + if tmp_sponsorship is None: + logWrite(f"Sponsorship of {holo_user.id} is nowhere to be found.") + return + + if tmp_sponsorship["sent"] is True: + return + + await msg.reply_text(locale("sponsorship_sent", "message"), reply_markup=ReplyKeyboardRemove()) + + sponsorship_content = [] + + for question in tmp_sponsorship['sponsorship']: + + if question == "expires": + sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question].strftime('%d.%m.%Y')}") + elif question == "proof": + filename = uuid1() + with open(f"tmp{sep}{filename}.jpg", "wb") as f: + f.write(tmp_sponsorship['sponsorship']['proof']) + else: + sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}") + + await app.send_photo(chat_id=configGet("admin_group"), photo=f"tmp{sep}{filename}.jpg", caption=(locale("sponsor_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(sponsorship_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton(text=str(locale("sponsor_yes", "button")), callback_data=f"sponsor_yes_{holo_user.id}") + ], + [ + InlineKeyboardButton(text=str(locale("sponsor_no", "button")), callback_data=f"sponsor_no_{holo_user.id}") + ] + ] + ) + ) + + remove(f"tmp{sep}{filename}.jpg") + + logWrite(f"User {holo_user.id} sent his sponsorship application and it will now be reviewed") + + col_tmp.update_one({"user": holo_user.id, "type": "sponsorship"}, {"$set": {"sent": True}}) + + return + confirmation_2 = [] for pattern in all_locales("confirm", "keyboard"): confirmation_2.append(pattern[1][0]) @app.on_message(~ filters.scheduled & filters.private & filters.command(confirmation_2, prefixes=[""])) -async def confirm_no(app, msg): +async def confirm_no(app, msg, kind: Literal["application", "sponsorship"] = "unknown"): holo_user = HoloUser(msg.from_user) - if (holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True): + if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)): holo_user.application_restart() await welcome_pass(app, msg, once_again=True) logWrite(f"User {msg.from_user.id} restarted the application due to typo in it") + return + + if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)): + holo_user.sponsorship_restart() + await app.send_message(holo_user.id, locale(f"sponsor1", "message", locale=holo_user.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale)))) + logWrite(f"User {msg.from_user.id} restarted the sponsorship application due to typo in it") + return # ============================================================================================================================== \ No newline at end of file diff --git a/modules/handlers/everything.py b/modules/handlers/everything.py index b42ca19..5a37c89 100644 --- a/modules/handlers/everything.py +++ b/modules/handlers/everything.py @@ -52,6 +52,7 @@ async def any_stage(app, msg): if msg.text is not None: await holo_user.application_next(msg.text, msg=msg) + await holo_user.sponsorship_next(msg.text, msg=msg) # user_stage = configGet("stage", file=str(msg.from_user.id)) diff --git a/modules/handlers/sponsorship.py b/modules/handlers/sponsorship.py index 393405e..1fb1adb 100644 --- a/modules/handlers/sponsorship.py +++ b/modules/handlers/sponsorship.py @@ -1,6 +1,13 @@ from app import app from pyrogram import filters +from classes.holo_user import HoloUser + @app.on_message(~ filters.scheduled & filters.photo & filters.private) async def sponsor_proof(app, msg): - pass \ No newline at end of file + + if msg.via_bot is None: + + holo_user = HoloUser(msg.from_user) + + await holo_user.sponsorship_next(msg.text, msg=msg, photo=msg.photo) \ No newline at end of file diff --git a/modules/scheduled.py b/modules/scheduled.py index 81c5ce6..8eb63ec 100644 --- a/modules/scheduled.py +++ b/modules/scheduled.py @@ -5,9 +5,10 @@ from app import app from pyrogram.types import BotCommand, BotCommandScopeChat from pyrogram.errors import bad_request_400 from pyrogram.enums.chat_members_filter import ChatMembersFilter +from classes.holo_user import HoloUser from modules.utils import configGet, locale, logWrite from dateutil.relativedelta import relativedelta -from modules.database import col_applications +from modules.database import col_applications, col_sponsorships scheduler = AsyncIOScheduler() @@ -47,6 +48,28 @@ if configGet("enabled", "scheduler", "birthdays"): if configGet("enabled", "scheduler", "sponsorships"): @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)}}): + try: + tg_user = await app.get_users(entry["user"]) + until_expiry = relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days + await app.send_message( tg_user, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore + logWrite(f"Notified user that sponsorship expires in {until_expiry} days") + 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()}}): + try: + holo_user = HoloUser(entry["user"]) + await app.send_message( entry["user"], locale("sponsorships_expired", "message") ) # type: ignore + await holo_user.reset_label(configGet("destination_group")) + try: + tg_user = await app.get_users(entry["user"]) + logWrite(f"Notified user that sponsorship expires in {until_expiry} days") + except Exception as exp: + logWrite(f"Could not find user {entry['user']} notify about sponsorship expired due to '{exp}'") + except Exception as exp: + logWrite(f"Could not reset label of user {entry['user']} due to '{exp}'") + continue logWrite("Sponsorships check performed")