diff --git a/holochecker.py b/holochecker.py index 63bf2fc..e7b9859 100644 --- a/holochecker.py +++ b/holochecker.py @@ -1,4 +1,5 @@ from os import getpid, makedirs +from time import time from modules.utils import * from modules.inline import * from app import app @@ -54,7 +55,16 @@ if __name__ == "__main__": app.start() try: - app.send_message(configGet("owner"), f"Starting up with pid `{pid}`") + if path.exists(path.join(configGet("cache", "locations"), "shutdown_time")): + downtime = relativedelta(datetime.now(), datetime.fromtimestamp(jsonLoad(path.join(configGet("cache", "locations"), "shutdown_time"))["timestamp"])) + if downtime.days >= 1: + app.send_message(configGet("owner"), locale("startup_downtime_days", "message").format(pid, downtime.days)) + elif downtime.hours >= 1: + app.send_message(configGet("owner"), locale("startup_downtime_hours", "message").format(pid, downtime.hours)) + else: + app.send_message(configGet("owner"), locale("startup_downtime_minutes", "message").format(pid, downtime.minutes)) + else: + app.send_message(configGet("owner"), locale("startup", "message").format(pid)) except bad_request_400.PeerIdInvalid: logWrite(f"Could not send startup message to bot owner. Perhaps user has not started the bot yet.") @@ -63,10 +73,13 @@ if __name__ == "__main__": idle() try: - app.send_message(configGet("owner"), f"Shutting with pid `{pid}`") + app.send_message(configGet("owner"), locale("shutdown", "message").format(pid)) except bad_request_400.PeerIdInvalid: logWrite(f"Could not send shutdown message to bot owner. Perhaps user has not started the bot yet.") app.stop() + + makedirs(configGet("cache", "locations"), exist_ok=True) + jsonSave({"timestamp": time()}, path.join(configGet("cache", "locations"), "shutdown_time")) killProc(pid) \ No newline at end of file diff --git a/locale/uk.json b/locale/uk.json index ab8091d..5f4b8b6 100644 --- a/locale/uk.json +++ b/locale/uk.json @@ -38,7 +38,9 @@ "sponsor_got": "Отримано форму на спонсорство від `{0}`\n\nІм'я тг: `{1}`\nЮзернейм: @{2}\n\n**Дані форми:**\n{3}", "shutdown": "Вимкнення бота з підом `{0}`", "startup": "Запуск бота з підом `{0}`", - "startup_downtime": "Запуск бота з підом `{0}` (лежав {1})", + "startup_downtime_minutes": "Запуск бота з підом `{0}` (лежав {1} хв.)", + "startup_downtime_hours": "Запуск бота з підом `{0}` (лежав {1} год.)", + "startup_downtime_days": "Запуск бота з підом `{0}` (лежав {1} дн.)", "approved": "Вітаємо! Твою анкету переглянули та підтвердили твоє право на вступ. Скористайся кнопкою під повідомленням щоб вступити до нашої лампової спільноти!", "approved_joined": "Вітаємо! Твою анкету переглянули та підтвердили її правильність. Дякуємо за витрачений на заповнення час та гарного дня!", "read_rules": "Будь ласка, прочитай ці правила перш ніж натискати на кнопку та приєднуватись до чату.", @@ -90,7 +92,7 @@ "sponsorships_expires": "⚠️ **Нагадування**\nНадана платна підписка припинить діяти **за {0} д**. Будь ласка, оновіть дані про неї командою /sponsorship інакше роль буде втрачено!", "sponsorships_expired": "⚠️ **Нагадування**\nТермін дії вказаної підписки сплив. Для повторного отримання ролі користуйся командою /sponsorship.", "label_too_long": "Довжина назви ролі не повинна перевищувати 16 символів", - "finish_sponsorship": "❌ **Дія неможлива**\nПерш ніж заповнювати анкету, треба завершити заповнення форми спонсора.", + "finish_sponsorship": "❌ **Дія неможлива**\nПерш ніж заповнювати анкету, треба завершити заповнення форми спонсора або перервати його командою /cancel.", "finish_application": "❌ **Дія неможлива**\nПерш ніж заповнювати форму спонсора, треба завершити заповнення анкети.", "nearby_invalid": "ℹ️ **Місце не знайдено**\nЗа наданим запитом не знайдено місце з координатами. Спробуйте ще раз формулючи запит в стилі \"Чернівці\" або \"Київська область\".", "nearby_error": "⚠️ **Сталась помилка**\n\nПомилка: `{0}`\n\nTraceback:\n```\n{1}\n```", @@ -100,15 +102,18 @@ "identify_invalid_syntax": "Неправильний синтаксис!\nТреба: `/identify ID/NAME/USERNAME`", "identify_not_found": "Не знайдено користувачів за запитом **{0}**", "identify_success": "Користувач `{0}`\n\nІм'я: {1}\nЮзернейм: {2}\nЄ в чаті: {3}\nЄ адміном: {4}\nРоль: {5}\nНаявна анкета: {6}\nНаявне спонсорство: {7}", - "spoiler_started": "Розпочато створення спойлера. Надішліть щось", + "spoiler_started": "Розпочато створення спойлера. Будь ласка, оберіть категорію спойлера за допомогою клавіатури бота.", "spoiler_unfinished": "У вас ще є незавершений спойлер. Надішліть /cancel щоб зупинити його створення", "spoiler_cancel": "Створення спойлера було припинено", - "spoiler_empty": "Спойлер без опису", - "spoiler_described": "Спойлер: {0}", + "spoiler_empty": "Спойлер категорії \"{0}\" без опису", + "spoiler_described": "Спойлер категорії \"{0}\": {1}", "spoiler_description_enter": "Добре, введіть бажаний опис спойлера", - "spoiler_using_description": "Встановлено опис спойлера: {0}", - "spoiler_send_description": "Майже впорались. Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.", + "spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео а також гіф зображення (1 шт.)", + "spoiler_send_description": "Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.", "spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.", + "spoiler_incorrect_content": "Бот не підтримує такий контент. Будь ласка, надішли текст, фото, відео або анімацію (гіф).", + "spoiler_incorrect_category": "Вказана категорія не є дійсною. Будь ласка, користуйся клавіатурою бота (кнопка біля 📎) для вибору категорії.", + "spoiler_in_progress": "❌ **Дія неможлива**\nПерш ніж починати нову дію, треба завершити створення спойлера або перервати його командою /cancel.", "yes": "Так", "no": "Ні", "voice_message": [ @@ -132,6 +137,11 @@ "question_streamer": "Стрімер:", "question_expires": "Підписка до:", "question_label": "Хоче роль:" + }, + "spoiler_categories": { + "nsfw": "NSFW контент", + "deanon": "Деанон холо-учасників", + "other": "Інше" } }, "keyboard": { @@ -156,7 +166,7 @@ "Ні, повторно заповнити" ] ], - "spoiler_description": [ + "spoiler_categories": [ [ "NSFW контент" ], @@ -164,7 +174,7 @@ "Деанон холо-учасників" ], [ - "Інше (надішліть свій текст)" + "Інше" ] ] }, diff --git a/modules/commands/application.py b/modules/commands/application.py index 46b0122..b1d429a 100644 --- a/modules/commands/application.py +++ b/modules/commands/application.py @@ -11,7 +11,7 @@ from dateutil.relativedelta import relativedelta from modules.database import col_applications from modules import custom_filters -# Applications command ========================================================================================================= +# Application command ========================================================================================================== @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["application"], prefixes=["/"]) & custom_filters.admin) async def cmd_application(app: Client, msg: Message): @@ -55,42 +55,6 @@ async def cmd_application(app: Client, msg: Message): logWrite(f"User {msg.from_user.id} requested application of {holo_user.id}") await msg.reply_text(locale("contact", "message", locale=msg.from_user).format(holo_user.id, "\n".join(application_content), application_status), parse_mode=ParseMode.MARKDOWN, quote=should_quote(msg)) - - # if (path.exists(f"{configGet('data', 'locations')}{sep}users{sep}{msg.command[1]}.json") and jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{msg.command[1]}.json")["approved"]): - # user_id = int(msg.command[1]) - # else: - # list_of_users = [] - # async for m in app.get_chat_members(configGet("users", "groups"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]): - # list_of_users.append(m) - # user_id = list_of_users[0].user.id - # try: - # user_data = jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{user_id}.json") - # application = jsonLoad(f"{configGet('data', 'locations')}{sep}applications.json")[str(user_id)] - # application_content = [] - # i = 1 - # for question in configGet("application", file=str(msg.from_user.id)): - # if i == 2: - # age = relativedelta(datetime.now(), datetime.strptime(application['application']['2'], '%d.%m.%Y')) - # application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {application['application']['2']} ({age.years} р.)") - # else: - # application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {application['application'][question]}") - # i += 1 - # if user_data["sent"]: - # if user_data["approved"]: - # application_status = locale("application_status_accepted", "message").format((await app.get_users(application["approved_by"])).first_name, datetime.fromtimestamp(application["approval_date"]).strftime("%d.%m.%Y, %H:%M")) - # elif application["rejected"]: - # application_status = locale("application_status_rejected", "message").format((await app.get_users(application["rejected_by"])).first_name, datetime.fromtimestamp(application["refusal_date"]).strftime("%d.%m.%Y, %H:%M")) - # else: - # application_status = locale("application_status_on_hold", "message") - # else: - # if user_data["approved"]: - # application_status = locale("application_status_accepted", "message").format((await app.get_users(application["approved_by"])).first_name, datetime.fromtimestamp(application["approval_date"]).strftime("%d.%m.%Y, %H:%M")) - # elif application["rejected"]: - # application_status = locale("application_status_rejected", "message").format((await app.get_users(application["rejected_by"])).first_name, datetime.fromtimestamp(application["refusal_date"]).strftime("%d.%m.%Y, %H:%M")) - # else: - # application_status = locale("application_status_not_send", "message") - # logWrite(f"User {msg.from_user.id} requested application of {user_id}") - # await msg.reply_text(locale("contact", "message").format(str(user_id), "\n".join(application_content), application_status), quote=should_quote(msg)) except IndexError: await msg.reply_text(locale("application_invalid_syntax", "message", locale=msg.from_user), quote=should_quote(msg)) diff --git a/modules/commands/cancel.py b/modules/commands/cancel.py index f0755af..a0d755c 100644 --- a/modules/commands/cancel.py +++ b/modules/commands/cancel.py @@ -1,14 +1,16 @@ from app import app from pyrogram import filters -from pyrogram.types import Message +from pyrogram.types import Message, ReplyKeyboardRemove from pyrogram.client import Client from modules.utils import should_quote, logWrite, locale from modules.database import col_tmp, col_spoilers from modules import custom_filters +# Cancel command =============================================================================================================== @app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("cancel", prefixes=["/"])) async def command_cancel(app: Client, msg: Message): col_tmp.delete_many( {"user": msg.from_user.id} ) col_spoilers.delete_many( {"user": msg.from_user.id, "completed": False} ) - await msg.reply_text(locale("cancel", "message", locale=msg.from_user), quote=should_quote(msg)) - logWrite(f"Cancelling all ongoing tmp operations for {msg.from_user.id}") \ No newline at end of file + await msg.reply_text(locale("cancel", "message", locale=msg.from_user), quote=should_quote(msg), reply_markup=ReplyKeyboardRemove()) + logWrite(f"Cancelling all ongoing tmp operations for {msg.from_user.id}") +# ============================================================================================================================== \ No newline at end of file diff --git a/modules/commands/identify.py b/modules/commands/identify.py index 6f83ed0..953fd42 100644 --- a/modules/commands/identify.py +++ b/modules/commands/identify.py @@ -9,8 +9,9 @@ from classes.holo_user import HoloUser, UserNotFoundError, UserInvalidError from modules.utils import jsonLoad, should_quote, logWrite, locale, download_tmp, create_tmp, find_user from modules import custom_filters +# Identify command ============================================================================================================= @app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("identify", prefixes=["/"]) & custom_filters.admin) -async def command_identify(app: Client, msg: Message): +async def cmd_identify(app: Client, msg: Message): if len(msg.command) != 2: await msg.reply_text(locale("identify_invalid_syntax", "message", locale=msg.from_user)) @@ -60,4 +61,5 @@ async def command_identify(app: Client, msg: Message): quote=should_quote(msg) ) - logWrite(f"User {msg.from_user.id} identified user {holo_user.id}") \ No newline at end of file + logWrite(f"User {msg.from_user.id} identified user {holo_user.id}") +# ============================================================================================================================== \ No newline at end of file diff --git a/modules/commands/label.py b/modules/commands/label.py index cfe5967..e0e711e 100644 --- a/modules/commands/label.py +++ b/modules/commands/label.py @@ -6,6 +6,7 @@ from modules.utils import locale, should_quote, find_user from classes.holo_user import HoloUser, LabelTooLongError from modules import custom_filters +# Label command ================================================================================================================ @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["label"], prefixes=["/"]) & custom_filters.admin) async def cmd_label(app: Client, msg: Message): @@ -34,4 +35,5 @@ async def cmd_label(app: Client, msg: Message): await msg.reply_text(f"Setting **{target.id}**'s label to **{label}**...", quote=should_quote(msg)) else: - await msg.reply_text(f"User not found") \ No newline at end of file + await msg.reply_text(f"User not found") +# ============================================================================================================================== \ No newline at end of file diff --git a/modules/commands/nearby.py b/modules/commands/nearby.py index 6ef09de..f0a80a4 100644 --- a/modules/commands/nearby.py +++ b/modules/commands/nearby.py @@ -38,7 +38,6 @@ async def cmd_nearby(app: Client, msg: Message): # Find all users registered in the area provided output = [] applications_nearby = col_applications.find( {"application.3.location": { "$nearSphere": {"$geometry": {"type": "Point", "coordinates": [location[0], location[1]]}, "$maxDistance": configGet("search_radius")*1000} } } ) - # {"application": {"3": {"location": {"$near": { "$geometry": { "type": "Point", "coordinates": location }, "$maxDistance": 30000 }} } } } ) for entry in applications_nearby: if not entry["user"] == msg.from_user.id: @@ -56,18 +55,4 @@ async def cmd_nearby(app: Client, msg: Message): await msg.reply_text(locale("nearby_result", "message", locale=holo_user).format("\n".join(output)), quote=should_quote(msg)) else: await msg.reply_text(locale("nearby_empty", "message", locale=holo_user), quote=should_quote(msg)) - - # if not path.exists(f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json"): - # jsonSave(jsonLoad(f"{configGet('data', 'locations')}{sep}sponsor_default.json"), f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json") - # sponsor = jsonLoad(f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json") - # if sponsor["approved"]: - # if sponsor["expires"] is not None: - # if datetime.strptime(sponsor["expires"], "%d.%m.%Y") > datetime.now(): - # await msg.reply_text(f"You have an active sub til **{sponsor['expires']}**.") - # else: - # await msg.reply_text(f"Your sub expired {int((datetime.now()-datetime.strptime(sponsor['expires'], '%d.%m.%Y')).days)} days ago.") - # elif sponsor["approved"]: - # await msg.reply_text(f"Your sub expiration date is not valid.") - # else: - # await msg.reply_text(f"You have no active subscription.") # ============================================================================================================================== \ No newline at end of file diff --git a/modules/commands/reapply.py b/modules/commands/reapply.py index 35f7467..c817c77 100644 --- a/modules/commands/reapply.py +++ b/modules/commands/reapply.py @@ -15,7 +15,7 @@ async def cmd_reapply(app: Client, msg: Message): holo_user = HoloUser(msg.from_user) # Check if user has approved/rejected tmp application - if (holo_user.application_state()[0] in ["approved", "rejected"]) or (holo_user.application_state()[0] == "none"): + if ((holo_user.application_state()[0] in ["approved", "rejected"]) or (holo_user.application_state()[0] == "none")) and holo_user.spoiler_state() is False: # Check if user's tmp application is already completed or even sent if ((holo_user.application_state()[1] is True) and (not col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"])) or (holo_user.application_state()[0] == "none"): @@ -51,6 +51,10 @@ async def cmd_reapply(app: Client, msg: Message): ] ])) + elif holo_user.spoiler_state() is True: + + await msg.reply_text(locale("spoiler_in_progress", "message", locale=holo_user)) + else: if (holo_user.application_state()[0] == "fill") and (col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"] is True): diff --git a/modules/commands/reboot.py b/modules/commands/reboot.py index 8005a1a..74834aa 100644 --- a/modules/commands/reboot.py +++ b/modules/commands/reboot.py @@ -1,21 +1,24 @@ from app import app -from os import getpid +from os import getpid, makedirs, path from sys import exit +from time import time from pyrogram import filters from pyrogram.types import Message from pyrogram.client import Client -from modules.utils import locale, logWrite, should_quote +from modules.utils import configGet, jsonSave, locale, logWrite, should_quote from modules.scheduled import scheduler from modules import custom_filters pid = getpid() -# Shutdown command ============================================================================================================= +# Reboot command =============================================================================================================== @app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["/"]) & custom_filters.admin) async def cmd_kill(app: Client, msg: Message): logWrite(f"Shutting down bot with pid {pid}") await msg.reply_text(locale("shutdown", "message", locale=msg.from_user).format(pid), quote=should_quote(msg)) scheduler.shutdown() + makedirs(configGet("cache", "locations"), exist_ok=True) + jsonSave({"timestamp": time()}, path.join(configGet("cache", "locations"), "shutdown_time")) exit() # ============================================================================================================================== \ No newline at end of file diff --git a/modules/commands/resetcommands.py b/modules/commands/resetcommands.py index 9ed0657..5f5ef15 100644 --- a/modules/commands/resetcommands.py +++ b/modules/commands/resetcommands.py @@ -9,9 +9,9 @@ from modules import custom_filters pid = getpid() -# Shutdown command ============================================================================================================= +# Reset commands command ======================================================================================================= @app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["resetcommands"], prefixes=["/"]) & custom_filters.admin) -async def cmd_kill(app: Client, msg: Message): +async def cmd_resetcommands(app: Client, msg: Message): if msg.from_user.id == configGet("owner"): diff --git a/modules/commands/spoiler.py b/modules/commands/spoiler.py index 3239178..cecac06 100644 --- a/modules/commands/spoiler.py +++ b/modules/commands/spoiler.py @@ -1,6 +1,6 @@ from app import app from pyrogram import filters -from pyrogram.types import Message, ForceReply +from pyrogram.types import Message, ReplyKeyboardMarkup from pyrogram.client import Client from classes.holo_user import HoloUser, UserInvalidError, UserNotFoundError from modules.logging import logWrite @@ -25,15 +25,17 @@ async def cmd_spoiler(app: Client, msg: Message): { "user": msg.from_user.id, "completed": False, + "category": None, "description": None, "photo": None, "video": None, "animation": None, + "caption": None, "text": None } ) - await msg.reply_text(locale("spoiler_started", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_content", "force_reply", locale=msg.from_user))) + await msg.reply_text(locale("spoiler_started", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_categories", "keyboard"), resize_keyboard=True, one_time_keyboard=True)) logWrite(f"User {msg.from_user.id} started creating new spoiler") else: diff --git a/modules/commands/sponsorship.py b/modules/commands/sponsorship.py index ea869b1..4896b2a 100644 --- a/modules/commands/sponsorship.py +++ b/modules/commands/sponsorship.py @@ -10,9 +10,13 @@ from modules.database import col_applications # Sponsorship command ========================================================================================================== @app.on_message(custom_filters.enabled_sponsorships & ~filters.scheduled & filters.command(["sponsorship"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin)) async def cmd_sponsorship(app: Client, msg: Message): - if HoloUser(msg.from_user).application_state()[0] == "fill": + holo_user = HoloUser(msg.from_user) + if holo_user.application_state()[0] == "fill": await msg.reply_text(locale("finish_application", "message", locale=msg.from_user), quote=should_quote(msg)) return + if holo_user.spoiler_state() is True: + await msg.reply_text(locale("spoiler_in_progress", "message", locale=holo_user)) + return await msg.reply_text(locale("sponsorship_apply", "message", locale=msg.from_user), reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text=str(locale("sponsor_apply", "button", locale=msg.from_user)), callback_data=f"sponsor_apply_{msg.from_user.id}")]]), quote=should_quote(msg)) # else: # await msg.reply_text(locale("sponsorship_application_empty", "message")) diff --git a/modules/commands/start.py b/modules/commands/start.py index 66cb464..109a743 100644 --- a/modules/commands/start.py +++ b/modules/commands/start.py @@ -33,11 +33,11 @@ async def cmd_start(app: Client, msg: Message): try: spoiler = col_spoilers.find_one( {"_id": ObjectId(msg.command[1])} ) if spoiler["photo"] is not None: - await msg.reply_photo(spoiler["photo"]) + await msg.reply_photo(spoiler["photo"], caption=spoiler["caption"]) if spoiler["video"] is not None: - await msg.reply_video(spoiler["video"]) + await msg.reply_video(spoiler["video"], caption=spoiler["caption"]) if spoiler["animation"] is not None: - await msg.reply_animation(spoiler["animation"]) + await msg.reply_animation(spoiler["animation"], caption=spoiler["caption"]) if spoiler["text"] is not None: await msg.reply_text(spoiler["text"]) except InvalidId: diff --git a/modules/handlers/confirmation.py b/modules/handlers/confirmation.py index 76413d2..cda9537 100644 --- a/modules/handlers/confirmation.py +++ b/modules/handlers/confirmation.py @@ -93,9 +93,6 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s return - # configSet(["sent"], True, file=str(holo_user.id)) - # configSet(["confirmed"], True, file=str(holo_user.id)) - if configGet("enabled", "features", "sponsorships") is True: if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)): diff --git a/modules/handlers/everything.py b/modules/handlers/everything.py index c1b2da6..5639271 100644 --- a/modules/handlers/everything.py +++ b/modules/handlers/everything.py @@ -1,3 +1,4 @@ +from traceback import print_exc from app import app, isAnAdmin import asyncio from pyrogram import filters @@ -6,7 +7,6 @@ from pyrogram.client import Client from classes.holo_user import HoloUser from modules.utils import configGet, logWrite, locale, all_locales from modules.database import col_messages, col_spoilers -from bson import ObjectId async def message_involved(msg: Message) -> bool: message = col_messages.find_one({"destination.id": msg.reply_to_message.id, "destination.chat": msg.reply_to_message.chat.id}) @@ -47,9 +47,6 @@ async def any_stage(app: Client, msg: Message): adm_context=await isAnAdmin(msg.from_user.id) ) - # await msg.reply_text(locale("message_sent", "message"), quote=should_quote(msg)) - # col_messages.insert_one({"origin": {"chat": msg.chat.id, "id": msg.id}, "destination": {"chat": new_message.chat.id, "id": new_message.id}}) - return if msg.text is not None: @@ -67,108 +64,82 @@ async def any_stage(app: Client, msg: Message): if spoiler is None: return - if msg.photo is not None: - col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"photo": msg.photo.file_id}} ) - await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user))) - logWrite(f"Adding photo with id {msg.photo.file_id} to {msg.from_user.id}'s spoiler") + if spoiler["category"] is None: + + found = False + + # Find category in all locales + for lc in all_locales("spoiler_categories", "message"): + for key in lc: + if lc[key] == msg.text: + found = True + category = key + + if found is False: + await msg.reply_text(locale("spoiler_incorrect_category", "message", locale=msg.from_user)) + return + + col_spoilers.find_one_and_update( {"_id": spoiler["_id"]}, {"$set": {"category": category}} ) + await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user))) return + if spoiler["description"] is None and (spoiler["photo"] is None and spoiler["video"] is None and spoiler["animation"] is None and spoiler["text"] is None): + + # for lc in all_locales("spoiler_description", "keyboard"): + # if msg.text == lc[-1][0]: + # await msg.reply_text(locale("spoiler_description_enter", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user))) + # return + + if msg.text != "-": + col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text}} ) + else: + col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": ""}} ) + + logWrite(f"Adding description '{msg.text}' to {msg.from_user.id}'s spoiler") + await msg.reply_text(locale("spoiler_using_description", "message", locale=msg.from_user).format(msg.text), reply_markup=ForceReply(placeholder=locale("spoiler_content", "force_reply", locale=msg.from_user))) + + return + + ready = False + + if msg.photo is not None: + col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"photo": msg.photo.file_id, "caption": msg.caption, "completed": True}} ) + logWrite(f"Adding photo with id {msg.photo.file_id} to {msg.from_user.id}'s spoiler") + ready = True + if msg.video is not None: - col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"video": msg.video.file_id}} ) - await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user))) + col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"video": msg.video.file_id, "caption": msg.caption, "completed": True}} ) logWrite(f"Adding video with id {msg.video.file_id} to {msg.from_user.id}'s spoiler") - return + ready = True if msg.animation is not None: - col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"animation": msg.animation.file_id}} ) - await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user))) + col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"animation": msg.animation.file_id, "caption": msg.caption, "completed": True}} ) logWrite(f"Adding animation with id {msg.animation.file_id} to {msg.from_user.id}'s spoiler") - return + ready = True if spoiler["photo"] is None and spoiler["video"] is None and spoiler["animation"] is None and spoiler["text"] is None: - col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"text": msg.text}} ) - await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user))) - logWrite(f"Adding text '{msg.text}' to {msg.from_user.id}'s spoiler") + if msg.text is not None: + col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"text": msg.text, "completed": True}} ) + logWrite(f"Adding text '{msg.text}' to {msg.from_user.id}'s spoiler") + ready = True + + if ready 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__()}")]])) else: - for lc in all_locales("spoiler_description", "keyboard"): - if msg.text == lc[-1][0]: - await msg.reply_text(locale("spoiler_description_enter", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user))) - return - if msg.text != "-": - col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text, "completed": True}} ) - else: - col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": None, "completed": True}} ) - logWrite(f"Adding description '{msg.text}' to {msg.from_user.id}'s spoiler") - await msg.reply_text(locale("spoiler_using_description", "message", locale=msg.from_user).format(msg.text), reply_markup=ReplyKeyboardRemove()) - await msg.reply_text(locale("spoiler_ready", "message", locale=msg.from_user), quote=False, 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_incorrect_content", "message", locale=msg.from_user)) - # user_stage = configGet("stage", file=str(msg.from_user.id)) - - # if user_stage == 1: - # await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply")))) - # logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application") - # configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id)) - # configSet(["stage"], user_stage+1, file=str(msg.from_user.id)) - - # elif user_stage == 2: - - # try: - - # configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id)) - - # input_dt = datetime.strptime(msg.text, "%d.%m.%Y") - - # if datetime.now() <= input_dt: - # logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to joking") - # await msg.reply_text(locale("question2_joke", "message"), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply")))) - - # elif ((datetime.now() - input_dt).days) < ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days): - # logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to being underage") - # await msg.reply_text(locale("question2_underage", "message").format(str(configGet("age_allowed"))), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply")))) - - # else: - # logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application") - # await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply")))) - # configSet(["stage"], user_stage+1, file=str(msg.from_user.id)) - - # except ValueError: - # logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to sending invalid date format") - # await msg.reply_text(locale(f"question2_invalid", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage}", "force_reply")))) - - # else: - # if user_stage <= 9: - # logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application") - # await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply")))) - # configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id)) - # configSet(["stage"], user_stage+1, file=str(msg.from_user.id)) - # else: - # if not configGet("sent", file=str(msg.from_user.id)): - # if not configGet("confirmed", file=str(msg.from_user.id)): - # configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id)) - # application_content = [] - # i = 1 - # for question in configGet("application", file=str(msg.from_user.id)): - # application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {configGet('application', file=str(msg.from_user.id))[question]}") - # i += 1 - # await msg.reply_text(locale("confirm", "message").format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard"), resize_keyboard=True)) - # #configSet("sent", True, file=str(msg.from_user.id)) - # #configSet("application_date", int(time()), file=str(msg.from_user.id)) - # else: - # if not configGet("approved", file=str(msg.from_user.id)) and not configGet("rejected", file=str(msg.from_user.id)): - # await msg.reply_text(locale("already_sent", "message")) - # else: - # if not configGet("approved", file=str(msg.from_user.id)) and not configGet("rejected", file=str(msg.from_user.id)): - # await msg.reply_text(locale("already_sent", "message")) @app.on_message(~ filters.scheduled & filters.group) async def message_in_group(app: Client, msg: Message): if (msg.chat is not None) and (msg.via_bot is not None): if (msg.via_bot.id == (await app.get_me()).id) and (msg.chat.id == configGet("users", "groups")): if msg.text.startswith(locale("spoiler_described", "message").split()[0]) or msg.text.startswith(locale("spoiler_empty", "message").split()[0]): + logWrite(f"User {msg.from_user.id} sent spoiler to user's group") try: - await msg.forward(configGet("users", "groups"), disable_notification=True) - except: - pass + logWrite("Forwarding spoiler to admin's group") + await msg.copy(configGet("admin", "groups"), disable_notification=True) + except Exception as exp: + logWrite(f"Could not forward spoiler to admin's group due to '{exp}': {print_exc()}") return if configGet("remove_application_time") > 0: logWrite(f"User {msg.from_user.id} requested application in destination group, removing in {configGet('remove_application_time')} minutes") diff --git a/modules/handlers/welcome.py b/modules/handlers/welcome.py index 95ccf0f..45c2ca7 100644 --- a/modules/handlers/welcome.py +++ b/modules/handlers/welcome.py @@ -31,8 +31,6 @@ async def welcome_pass(app: Client, msg: Message, once_again: bool = True) -> No logWrite(f"User {msg.from_user.id} confirmed starting the application") await msg.reply_text(locale("question1", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("question1", "force_reply", locale=msg.from_user))) - # configSet(["stage"], 1, file=str(msg.from_user.id)) - # configSet(["sent"], False, file=str(msg.from_user.id)) welcome_2 = [] for pattern in all_locales("welcome", "keyboard"): diff --git a/modules/inline.py b/modules/inline.py index 2f30ac2..dec4344 100644 --- a/modules/inline.py +++ b/modules/inline.py @@ -28,7 +28,7 @@ async def inline_answer(client: Client, inline_query: InlineQuery): if spoil is not None: - desc = locale("spoiler_empty", "message", locale=inline_query.from_user) if spoil["description"] is None else locale("spoiler_described", "message", locale=inline_query.from_user).format(spoil["description"]) + desc = locale("spoiler_empty", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories")) if spoil["description"] == "" else locale("spoiler_described", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), spoil["description"]) results = [ InlineQueryResultArticle( diff --git a/validation/spoilers.json b/validation/spoilers.json index 1837cbb..8c6733d 100644 --- a/validation/spoilers.json +++ b/validation/spoilers.json @@ -3,10 +3,12 @@ "required": [ "user", "completed", + "category", "description", "photo", "video", "animation", + "caption", "text" ], "properties": { @@ -18,6 +20,11 @@ "bsonType": "bool", "description": "Whether spoiler is a completed one" }, + "category": { + "bsonType": ["string", "null"], + "enum": ["nsfw", "deanon", "other"], + "description": "Spoiler's category" + }, "description": { "bsonType": ["string", "null"], "description": "Spoiler's description" @@ -34,6 +41,10 @@ "bsonType": ["string", "null"], "description": "Spoilered animation/GIF" }, + "caption": { + "bsonType": ["string", "null"], + "description": "Spoilered caption for media" + }, "text": { "bsonType": ["string", "null"], "description": "Spoilered text"