6 Commits

29 changed files with 174 additions and 510 deletions

4
.gitignore vendored
View File

@@ -161,6 +161,4 @@ data
TASK.md TASK.md
inline_bot.py inline_bot.py
.vscode .vscode
migrate.py migrate.py
validation/*
!validation/*.json

View File

@@ -33,9 +33,7 @@ You can see config file with all the comments below:
"debug": false, "debug": false,
"owner": 0, "owner": 0,
"age_allowed": 0, "age_allowed": 0,
"age_maximum": 70,
"api": "http://example.com", "api": "http://example.com",
"issues": "https://github.com/example/test/issues/new",
"inline_preview_count": 7, "inline_preview_count": 7,
"remove_application_time": -1, "remove_application_time": -1,
"search_radius": 50, "search_radius": 50,
@@ -83,8 +81,7 @@ You can see config file with all the comments below:
"enabled": false "enabled": false
}, },
"spoilers": { "spoilers": {
"enabled": true, "enabled": true
"allow_external": true
} }
}, },
"scheduler": { "scheduler": {
@@ -107,11 +104,6 @@ You can see config file with all the comments below:
"cache_admins": { "cache_admins": {
"interval": 120, "interval": 120,
"enabled": true "enabled": true
},
"channels_monitor": {
"interval": 5,
"enabled": true,
"channels": []
} }
}, },
"locations": { "locations": {
@@ -152,6 +144,7 @@ You can see config file with all the comments below:
"permissions": [ "permissions": [
"users", "users",
"admins", "admins",
"group_users",
"group_admins" "group_admins"
], ],
"modules": [ "modules": [
@@ -160,7 +153,7 @@ You can see config file with all the comments below:
}, },
"warn": { "warn": {
"permissions": [ "permissions": [
"group_users_admins" "group_users"
], ],
"modules": [ "modules": [
"warnings" "warnings"
@@ -220,15 +213,6 @@ You can see config file with all the comments below:
"sponsorships" "sponsorships"
] ]
}, },
"issue": {
"permissions": [
"users",
"admins"
],
"modules": [
"general"
]
},
"application": { "application": {
"permissions": [ "permissions": [
"admins", "admins",

View File

@@ -1,6 +1,4 @@
from datetime import datetime from datetime import datetime
from asyncio import sleep
from ftfy import fix_text
from traceback import format_exc from traceback import format_exc
from app import app, isAnAdmin from app import app, isAnAdmin
from typing import Any, List, Literal, Union from typing import Any, List, Literal, Union
@@ -123,18 +121,13 @@ class HoloUser():
* adm_context (`bool`, *optional*): Whether context sender is an admin. Defaults to False. * adm_context (`bool`, *optional*): Whether context sender is an admin. Defaults to False.
""" """
if text is not None:
text = fix_text(text)
elif caption is not None:
caption = fix_text(caption)
# Check if any text available and log message sending # Check if any text available and log message sending
if text is not None: if text is not None:
logWrite(f"{context.from_user.id} sent message '{text}' to {self.id} (source message: {context.id})") logWrite(f"{context.from_user.id} sent message '{text}' to {self.id}")
elif caption is not None: elif caption is not None:
logWrite(f"{context.from_user.id} sent message '{caption}' to {self.id} (source message: {context.id})") logWrite(f"{context.from_user.id} sent message '{caption}' to {self.id}")
else: else:
logWrite(f"{context.from_user.id} sent message to {self.id} (source message: {context.id})") logWrite(f"{context.from_user.id} sent message to {self.id}")
# Add notices for admin or user # Add notices for admin or user
if text is not None: if text is not None:
@@ -171,7 +164,7 @@ class HoloUser():
elif file is not None: elif file is not None:
if isinstance(file, Document): if isinstance(file, Document):
file = file.file_id file = file.file_id
new_message = await origin.reply_cached_media(file, caption=caption, quote=True) new_message = await origin.reply_document(file, caption=caption, quote=True)
elif animation is not None: elif animation is not None:
if isinstance(animation, Animation): if isinstance(animation, Animation):
animation = animation.file_id animation = animation.file_id
@@ -196,7 +189,7 @@ class HoloUser():
elif file is not None: elif file is not None:
if isinstance(file, Document): if isinstance(file, Document):
file = file.file_id file = file.file_id
new_message = await app.send_cached_media(self.id, file, caption=caption) new_message = await app.send_document(self.id, file, caption=caption)
elif animation is not None: elif animation is not None:
if isinstance(animation, Animation): if isinstance(animation, Animation):
animation = animation.file_id animation = animation.file_id
@@ -234,7 +227,6 @@ class HoloUser():
try: try:
await app.promote_chat_member(configGet("users", "groups"), self.id, privileges=ChatPrivileges(can_pin_messages=True, can_manage_video_chats=True)) await app.promote_chat_member(configGet("users", "groups"), self.id, privileges=ChatPrivileges(can_pin_messages=True, can_manage_video_chats=True))
if not await isAnAdmin(self.id): if not await isAnAdmin(self.id):
await sleep(0.5)
await app.set_administrator_title(configGet("users", "groups"), self.id, label) await app.set_administrator_title(configGet("users", "groups"), self.id, label)
self.set("label", label) self.set("label", label)
except Exception as exp: except Exception as exp:
@@ -281,9 +273,10 @@ class HoloUser():
"""Reset application of a user in tmp collection and replace it with an empty one """Reset application of a user in tmp collection and replace it with an empty one
""" """
if col_tmp.find_one({"user": self.id, "type": "application"}) is None: if col_tmp.find_one({"user": self.id, "type": "application"}) is None:
col_tmp.insert_one(document=DefaultApplicationTemp(self.id, reapply=reapply).dict) col_tmp.insert_one(document=DefaultApplicationTemp(self.id).dict)
else: else:
col_tmp.find_one_and_replace({"user": self.id, "type": "application"}, DefaultApplicationTemp(self.id, reapply=reapply).dict) col_tmp.delete_one({"user": self.id, "type": "application"})
col_tmp.insert_one(document=DefaultApplicationTemp(self.id, reapply=reapply).dict)
async def application_next(self, query: str, msg: Message) -> None: async def application_next(self, query: str, msg: Message) -> None:
"""Move on filling application of user """Move on filling application of user
@@ -318,9 +311,6 @@ class HoloUser():
if progress["state"] == "fill" and progress["sent"] is False: if progress["state"] == "fill" and progress["sent"] is False:
if msg.text is not None:
msg.text = fix_text(msg.text)
if stage == 2: if stage == 2:
try: try:
@@ -330,7 +320,7 @@ class HoloUser():
await msg.reply_text(locale(f"question2_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale)))) await msg.reply_text(locale(f"question2_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
return return
if (datetime.now() <= input_dt) or ((datetime.now() - input_dt).days) > ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_maximum"))).days): if datetime.now() <= input_dt:
logWrite(f"User {msg.from_user.id} failed stage {stage} due to joking") logWrite(f"User {msg.from_user.id} failed stage {stage} due to joking")
await msg.reply_text(locale("question2_joke", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply", locale=self.locale)))) await msg.reply_text(locale("question2_joke", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply", locale=self.locale))))
return return
@@ -367,9 +357,6 @@ class HoloUser():
return return
elif stage == 10: elif stage == 10:
if len(query) > 1024:
await msg.reply_text(locale("question10_too_long", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
return
progress["application"][str(stage)] = query progress["application"][str(stage)] = query
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "complete": True}}) col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "complete": True}})
application_content = [] application_content = []
@@ -389,9 +376,6 @@ class HoloUser():
await msg.reply_text(locale("confirm", "message", locale=self.locale).format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard", locale=self.locale), resize_keyboard=True)) await msg.reply_text(locale("confirm", "message", locale=self.locale).format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard", locale=self.locale), resize_keyboard=True))
else: else:
if len(query) > 256:
await msg.reply_text(locale("question_too_long", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
return
progress["application"][str(stage)] = query progress["application"][str(stage)] = query
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}}) col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
await msg.reply_text(locale(f"question{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply", locale=self.locale)))) await msg.reply_text(locale(f"question{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply", locale=self.locale))))
@@ -444,20 +428,10 @@ class HoloUser():
stage = progress["stage"] stage = progress["stage"]
if msg.text is not None:
msg.text = fix_text(msg.text)
elif msg.caption is not None:
msg.caption = fix_text(msg.caption)
if progress["state"] == "fill" and progress["sent"] is False: if progress["state"] == "fill" and progress["sent"] is False:
if stage == 1: if stage == 1:
if len(query) > 240:
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
await msg.reply_text(locale(f"sponsor1_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage}", "force_reply", locale=self.locale))))
return
progress["sponsorship"]["streamer"] = query progress["sponsorship"]["streamer"] = query
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}}) 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)))) 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))))

View File

@@ -3,9 +3,7 @@
"debug": false, "debug": false,
"owner": 0, "owner": 0,
"age_allowed": 0, "age_allowed": 0,
"age_maximum": 70,
"api": "http://example.com", "api": "http://example.com",
"issues": "https://github.com/example/test/issues/new",
"inline_preview_count": 7, "inline_preview_count": 7,
"remove_application_time": -1, "remove_application_time": -1,
"search_radius": 50, "search_radius": 50,
@@ -53,8 +51,7 @@
"enabled": false "enabled": false
}, },
"spoilers": { "spoilers": {
"enabled": true, "enabled": true
"allow_external": true
} }
}, },
"scheduler": { "scheduler": {
@@ -77,11 +74,6 @@
"cache_admins": { "cache_admins": {
"interval": 120, "interval": 120,
"enabled": true "enabled": true
},
"channels_monitor": {
"interval": 5,
"enabled": true,
"channels": []
} }
}, },
"locations": { "locations": {
@@ -122,6 +114,7 @@
"permissions": [ "permissions": [
"users", "users",
"admins", "admins",
"group_users",
"group_admins" "group_admins"
], ],
"modules": [ "modules": [
@@ -130,7 +123,7 @@
}, },
"warn": { "warn": {
"permissions": [ "permissions": [
"group_users_admins" "group_users"
], ],
"modules": [ "modules": [
"warnings" "warnings"
@@ -190,15 +183,6 @@
"sponsorships" "sponsorships"
] ]
}, },
"issue": {
"permissions": [
"users",
"admins"
],
"modules": [
"general"
]
},
"application": { "application": {
"permissions": [ "permissions": [
"admins", "admins",

View File

@@ -15,7 +15,6 @@ from modules.commands.application import *
from modules.commands.applications import * from modules.commands.applications import *
from modules.commands.cancel import * from modules.commands.cancel import *
from modules.commands.identify import * from modules.commands.identify import *
from modules.commands.issue import *
from modules.commands.label import * from modules.commands.label import *
from modules.commands.message import * from modules.commands.message import *
from modules.commands.nearby import * from modules.commands.nearby import *
@@ -32,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

@@ -9,7 +9,7 @@
"question4": "When did you first learn about Hololive?", "question4": "When did you first learn about Hololive?",
"question5": "What made you interested in Hololive?", "question5": "What made you interested in Hololive?",
"question6": "Which girl's content do you like the most?", "question6": "Which girl's content do you like the most?",
"question7": "Name the content of at least five **JAPANESE** girls you like the most.", "question7": "Name the content of at least five Japanese girls you like the most.",
"question8": "Do you watch streams of Hololive girls?", "question8": "Do you watch streams of Hololive girls?",
"question9": "Whose songs from Hololive do you like the most?", "question9": "Whose songs from Hololive do you like the most?",
"question10": "And finally, tell us a little about yourself. About hobbies, what you like to do. In one message, please.", "question10": "And finally, tell us a little about yourself. About hobbies, what you like to do. In one message, please.",
@@ -31,6 +31,7 @@
"approved_joined": "Congratulations! Your application has been reviewed and confirmed as correct. Thank you for your time and have a nice day!", "approved_joined": "Congratulations! Your application has been reviewed and confirmed as correct. Thank you for your time and have a nice day!",
"read_rules": "Please read these rules before clicking the button and joining the chat.", "read_rules": "Please read these rules before clicking the button and joining the chat.",
"rejected.": "Oh dear! Your application has been reviewed but not confirmed as eligible to join the community. Better luck next time!\n\nYou can try to reapply with the /reapply command.", "rejected.": "Oh dear! Your application has been reviewed but not confirmed as eligible to join the community. Better luck next time!\n\nYou can try to reapply with the /reapply command.",
"rejected_aggressive": "Oh dear! Your application has been reviewed, but not confirmed as eligible to join the community.",
"rejected_russian": "Russian warship, go fuck yourself!", "rejected_russian": "Russian warship, go fuck yourself!",
"approved_by": "✅ **Application approved**\nAdmin **{0}** has reviewed and approved application `{1}`.", "approved_by": "✅ **Application approved**\nAdmin **{0}** has reviewed and approved application `{1}`.",
"rejected_by": "❌ **Form rejected**\nAdmin **{0}** has reviewed and rejected form `{1}`.", "rejected_by": "❌ **Form rejected**\nAdmin **{0}** has reviewed and rejected form `{1}`.",
@@ -121,6 +122,7 @@
"button": { "button": {
"sub_yes": "✅ Accept", "sub_yes": "✅ Accept",
"sub_no": "❌ Reject", "sub_no": "❌ Reject",
"sub_aggressive": "🤡 Reject (Toxic)",
"sub_russian": "🇷🇺 Reject (Russian)", "sub_russian": "🇷🇺 Reject (Russian)",
"accepted": "✅ Accepted", "accepted": "✅ Accepted",
"declined": "❌ Rejected", "declined": "❌ Rejected",
@@ -143,6 +145,7 @@
"callback": { "callback": {
"sub_accepted": "✅ Application {0} has been approved", "sub_accepted": "✅ Application {0} has been approved",
"sub_rejected": "❌ Application {0} rejected", "sub_rejected": "❌ Application {0} rejected",
"sub_aggressive": "🤡 Application {0} rejected",
"sub_russian": "🇷🇺 Application {0} rejected", "sub_russian": "🇷🇺 Application {0} rejected",
"sus_allowed": "✅ Access {0} allowed", "sus_allowed": "✅ Access {0} allowed",
"sus_rejected": "❌ Access {0} denied", "sus_rejected": "❌ Access {0} denied",

View File

@@ -4,16 +4,15 @@
"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": "Чим тебе зацікавив Хололайв?",
"question6": "Контент якої дівчини тобі подобається найбільше?", "question6": "Контент якої дівчини тобі подобається найбільше?",
"question7": "Назви контент хоча б п'яти **ЯПОНСЬКИХ** холодівчат, які тобі подобаються найбільше.", "question7": "Назви контент хоча б п'яти японських холодівчат, які тобі подобаються найбільше.",
"question8": "Чи дивишся ти стріми дівчат Хололайву?", "question8": "Чи дивишся ти стріми дівчат Хололайву?",
"question9": "Чиї пісні з Хололайву тобі подобаються найбільше?", "question9": "Чиї пісні з Хололайву тобі подобаються найбільше?",
"question10": "Ну і нарешті, розкажи трохи про себе. Про хобі, чим тобі подобається займатись. Одним повідомленням, будь ласка.", "question10": "Ну і нарешті, розкажи трохи про себе. Про хобі, чим тобі подобається займатись. Одним повідомленням, будь ласка.",
"question_too_long": "Текст занадто довгий. Будь ласка, умісти відповідь у 256 символів.",
"question2_underage": "Вибач, але треба досягти віку {0} років, щоб приєднатись до нас. Такі обмеження існують для того, щоб всім у спільноті було цікаво одне з одним.", "question2_underage": "Вибач, але треба досягти віку {0} років, щоб приєднатись до нас. Такі обмеження існують для того, щоб всім у спільноті було цікаво одне з одним.",
"question2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`", "question2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
"question2_joke": "Шутнік, ми так і поняли. Але будь ласка, введи реальне значення.", "question2_joke": "Шутнік, ми так і поняли. Але будь ласка, введи реальне значення.",
@@ -21,11 +20,9 @@
"question3_found": "Використовую наступний результат:\n• {0} ({1})", "question3_found": "Використовую наступний результат:\n• {0} ({1})",
"question3_error": "⚠️ **Сталась помилка**\nНе вдалось отримати географічну мітку. Розробника повідомлено про цю помилку. Будь ласка, спробуйте ще раз.", "question3_error": "⚠️ **Сталась помилка**\nНе вдалось отримати географічну мітку. Розробника повідомлено про цю помилку. Будь ласка, спробуйте ще раз.",
"question3_traceback": "⚠️ **Сталась помилка**\nПомилка отримання геокодингу для `{0}`\nПомилка: `{1}`\n\nTraceback:\n```\n{2}\n```", "question3_traceback": "⚠️ **Сталась помилка**\nПомилка отримання геокодингу для `{0}`\nПомилка: `{1}`\n\nTraceback:\n```\n{2}\n```",
"question10_too_long": "Текст занадто довгий. Будь ласка, умісти відповідь у 1024 символи.",
"sponsorship_apply": " Оформіть платну підписку на когось з Холо, заповніть форму та отримайте особливу роль в якості винагороди!", "sponsorship_apply": " Оформіть платну підписку на когось з Холо, заповніть форму та отримайте особливу роль в якості винагороди!",
"sponsorship_applying": " Розпочато заповнення форми на отримання бонусів за платну підписку на холодівчат.", "sponsorship_applying": " Розпочато заповнення форми на отримання бонусів за платну підписку на холодівчат.",
"sponsor1": "На яку саме дівчину платна підписка?", "sponsor1": "На яку саме дівчину платна підписка?",
"sponsor1_invalid": "Будь ласка, введіть ім'я не довше за 240 символів",
"sponsor2": "До якої дати (`ДД.ММ.РРРР`) підписка?", "sponsor2": "До якої дати (`ДД.ММ.РРРР`) підписка?",
"sponsor2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`", "sponsor2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
"sponsor2_past": "Вказана дата знаходиться в минулому. Будь ласка, вкажіть правильний термін дії підписки", "sponsor2_past": "Вказана дата знаходиться в минулому. Будь ласка, вкажіть правильний термін дії підписки",
@@ -48,6 +45,7 @@
"approved_joined": "Вітаємо! Твою анкету переглянули та підтвердили її правильність. Дякуємо за витрачений на заповнення час та гарного дня!", "approved_joined": "Вітаємо! Твою анкету переглянули та підтвердили її правильність. Дякуємо за витрачений на заповнення час та гарного дня!",
"read_rules": "Будь ласка, прочитай ці правила перш ніж натискати на кнопку та приєднуватись до чату.", "read_rules": "Будь ласка, прочитай ці правила перш ніж натискати на кнопку та приєднуватись до чату.",
"rejected": "Ой лишенько! Твою анкету переглянули, однак не підтвердили право на вступ до спільноти. Better luck next time!\n\nТи можеш спробувати повторно заповнити анкету командою /reapply", "rejected": "Ой лишенько! Твою анкету переглянули, однак не підтвердили право на вступ до спільноти. Better luck next time!\n\nТи можеш спробувати повторно заповнити анкету командою /reapply",
"rejected_aggressive": "Ой лишенько! Твою анкету переглянули, однак не підтвердили право на вступ до спільноти.",
"rejected_russian": "русский военньій корабль, иди нахуй!", "rejected_russian": "русский военньій корабль, иди нахуй!",
"approved_by": "✅ **Анкету схвалено**\nАдмін **{0}** переглянув та схвалив анкету `{1}`.", "approved_by": "✅ **Анкету схвалено**\nАдмін **{0}** переглянув та схвалив анкету `{1}`.",
"rejected_by": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`.", "rejected_by": "❌ **Анкету відхилено**\nАдмін **{0}** переглянув та відхилив анкету `{1}`.",
@@ -91,7 +89,6 @@
"no_user_application": "Не знайдено користувачів за запитом **{0}**", "no_user_application": "Не знайдено користувачів за запитом **{0}**",
"user_invalid": "Надісланий користувач не має завершеної анкети.", "user_invalid": "Надісланий користувач не має завершеної анкети.",
"joined_false_link": "Користувач **{0}** (`{1}`) приєднався до групи не за своїм посиланням", "joined_false_link": "Користувач **{0}** (`{1}`) приєднався до групи не за своїм посиланням",
"joined_application": "{0} (@{1})\n\n**Дані анкети:**\n{2}",
"sponsorships_expires": "⚠️ **Нагадування**\nНадана платна підписка припинить діяти **за {0} д**. Будь ласка, оновіть дані про неї командою /sponsorship інакше роль буде втрачено!", "sponsorships_expires": "⚠️ **Нагадування**\nНадана платна підписка припинить діяти **за {0} д**. Будь ласка, оновіть дані про неї командою /sponsorship інакше роль буде втрачено!",
"sponsorships_expired": "⚠️ **Нагадування**\nТермін дії вказаної підписки сплив. Для повторного отримання ролі користуйся командою /sponsorship.", "sponsorships_expired": "⚠️ **Нагадування**\nТермін дії вказаної підписки сплив. Для повторного отримання ролі користуйся командою /sponsorship.",
"label_too_long": "Довжина назви ролі не повинна перевищувати 16 символів", "label_too_long": "Довжина назви ролі не повинна перевищувати 16 символів",
@@ -102,7 +99,6 @@
"nearby_result": "Результати пошуку:\n\n{0}", "nearby_result": "Результати пошуку:\n\n{0}",
"nearby_empty": "Здається, нікого поблизу немає.", "nearby_empty": "Здається, нікого поблизу немає.",
"cancel": "Всі поточні операції скасовано.", "cancel": "Всі поточні операції скасовано.",
"cancel_reapply": "Всі поточні операції скасовано.\nЩоб знову заповнити анкету користуйся /reapply",
"identify_invalid_syntax": "Неправильний синтаксис!\nТреба: `/identify ID/NAME/USERNAME`", "identify_invalid_syntax": "Неправильний синтаксис!\nТреба: `/identify ID/NAME/USERNAME`",
"identify_not_found": "Не знайдено користувачів за запитом **{0}**", "identify_not_found": "Не знайдено користувачів за запитом **{0}**",
"identify_success": "Користувач `{0}`\n\nІм'я: {1}\nЮзернейм: {2}\nЄ в чаті: {3}\nЄ адміном: {4}\nРоль: {5}\nНаявна анкета: {6}\nНаявне спонсорство: {7}", "identify_success": "Користувач `{0}`\n\nІм'я: {1}\nЮзернейм: {2}\nЄ в чаті: {3}\nЄ адміном: {4}\nРоль: {5}\nНаявна анкета: {6}\nНаявне спонсорство: {7}",
@@ -110,20 +106,14 @@
"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_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)", "spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)",
"spoiler_send_description": "Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.", "spoiler_send_description": "Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.",
"spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.", "spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.",
"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})**",
"not_member": "❌ **Дія неможлива**\nУ тебе немає заповненої та схваленої анкети. Заповни таку за допомогою /reapply та спробуй ще раз після її підтвердження.",
"issue": "**Допоможіть боту**\nЗнайшли баг або помилку? Маєте файну ідею для нової функції? Повідомте нас, створивши нову задачу на гіті.\n\nЗа можливості, опишіть свій запит максимально детально. Якщо є змога, також додайте скріншоти або додаткову відому інформацію.",
"yes": "Так", "yes": "Так",
"no": "Ні", "no": "Ні",
"voice_message": [ "voice_message": [
@@ -209,6 +199,7 @@
"button": { "button": {
"sub_yes": "✅ Прийняти", "sub_yes": "✅ Прийняти",
"sub_no": "❌ Відхилити", "sub_no": "❌ Відхилити",
"sub_aggressive": "🤡 Відхилити (Токс)",
"sub_russian": "🇷🇺 Відхилити (Русак)", "sub_russian": "🇷🇺 Відхилити (Русак)",
"sponsor_yes": "✅ Прийняти", "sponsor_yes": "✅ Прийняти",
"sponsor_no": "❌ Відхилити", "sponsor_no": "❌ Відхилити",
@@ -231,15 +222,13 @@
"done": "✅ Готово", "done": "✅ Готово",
"sponsor_apply": "Заповнити форму", "sponsor_apply": "Заповнити форму",
"sponsor_started": "Форму розпочато", "sponsor_started": "Форму розпочато",
"spoiler_view": "Переглянути", "spoiler_send": "Надіслати",
"spoiler_preview": опередній перегляд", "spoiler_view": ереглянути"
"spoiler_send_chat": "Надіслати в холо-чат",
"spoiler_send_other": "Надіслати в інший чат",
"issue": "🪄 Створити задачу"
}, },
"callback": { "callback": {
"sub_accepted": "✅ Анкету {0} схвалено", "sub_accepted": "✅ Анкету {0} схвалено",
"sub_rejected": "❌ Анкету {0} відхилено", "sub_rejected": "❌ Анкету {0} відхилено",
"sub_aggressive": "🤡 Анкету {0} відхилено",
"sub_russian": "🇷🇺 Анкету {0} відхилено", "sub_russian": "🇷🇺 Анкету {0} відхилено",
"sus_allowed": "✅ Доступ {0} дозволено", "sus_allowed": "✅ Доступ {0} дозволено",
"sus_rejected": "❌ Доступ {0} заборонено", "sus_rejected": "❌ Доступ {0} заборонено",
@@ -250,8 +239,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": {
@@ -274,7 +262,7 @@
"description": "Надіслати цей спойлер до чату" "description": "Надіслати цей спойлер до чату"
} }
}, },
"rules_msg": "📢Правила можуть доповнюватись та змінюватись, залежно від потреби. У такому разі, порушення, які були вчинені до введення (змінення) правила, порушеннями вважатися не будуть. Про всі зміни в правилах, ви будете проінформовані за допомогою закріплених повідомлень. Але вони не будуть закріплені на постійній основі, тому, час від часу, перевіряйте актуальність правил у боті.\n\n🔔Якщо ви бачите, як хтось із учасників порушив правила, тегніть одного із адмінів, у відповідь на повідомлення, яке, на вашу думку, є порушенням. У дописі до тегу, вкажіть, по якому пункту ви побачили порушення. Або перешліть повідомлення до будь кого із адміністраторів у особисті повідомлення, та коротко опишіть ситуацію.\nСписок адміністраторів: @Chirkopol @Za_NerZula @Denialvapr\nЗ питань функціонування бота звертайтесь до @Profitroll2281337\n\n❗Будь-який заборонений контент, може бути відправлений за допомогою команди /spoiler у бота - з повним описом контенту, що міститься під спойлером. За неправильний або некоректний опис, може бути видане попередження.\n\n‼Видалені або змінені повідомлення, все ще є повідомленнями від вашого імені, які могли побачити учасники чату, і які можуть бути відстежені через адмінську панель.\n\n🔨 За порушення - ви отримаєте попередження. За наявності 3-х попереджень - мут на добу. За повторні порушення, ви одразу отримаєте покарання, без додаткових попереджень.", "rules_msg": "📢Правила можуть доповнюватись та змінюватись, залежно від потреби. У такому разі, порушення, які були вчинені до введення (змінення) правила, порушеннями вважатися не будуть. Про всі зміни в правилах, ви будете проінформовані за допомогою закріплених повідомлень. Але вони не будуть закріплені на постійній основі, тому, час від часу, перевіряйте актуальність правил у боті.\n\n🔔Якщо ви бачите, як хтось із учасників порушив правила, тегніть одного із адмінів, у відповідь на повідомлення, яке, на вашу думку, є порушенням. У дописі до тегу, вкажіть, по якому пункту ви побачили порушення. Або перешліть повідомлення до будь кого із адміністраторів у особисті повідомлення, та коротко опишіть ситуацію.\nСписок адміністраторів: @Chirkopol @Za_NerZula @Denialvapr\nЗ питань функціонування бота звертайтесь до @Profitroll2281337\n\n❗Будь-який заборонений контент, може бути відправлений до чату за допомогою бота - https://t.me/spoilerobot з повним описом контенту, що міститься під спойлером. За неправильний або некоректний опис, може бути видане попередження.\n\n‼Видалені або змінені повідомлення, все ще є повідомленнями від вашого імені, які могли побачити учасники чату, і які можуть бути відстежені через адмінську панель.\n\n🔨 За порушення - ви отримаєте попередження. За наявності 3-х попереджень - мут на добу. За повторні порушення, ви одразу отримаєте покарання, без додаткових попереджень.",
"rules": [ "rules": [
"1⃣) \"HoloKyiv Chat\" та \"HoloUA (Hololive Ukraine) Chat\" створені виключно для українців (13+). В них можуть знаходитись тільки люди які: \n- Народились в Україні, та проживають, на данний момент, у ній.\n- Народились за межами України, але проживають у ній.\n- Народились в Україні але, на даний момент, не проживають у ній.\n\"HoloUA (Hololive Ukraine) Chat\" відкритий для усіх українців. Щоб потрапити до нього, заповніть, будь ласка, анкету, та дочекайтесь, поки її схвалять адміни.\nУ \"HoloKyiv Chat\" можна потрапити тільки особисто, якщо ви проживаєте у Київі, або є близьким другом одного із учасників чату. Із приводу додавання до чату пишіть @Chirkopol у приватні повідомлення.\n🔨 Якщо у процесі спілкування виявиться, що ви не українець, вас буде видалено із чату, до моменту, поки ви їм не станете. Без образ. Ми створюємо виключно українське ком'юніті.", "1⃣) \"HoloKyiv Chat\" та \"HoloUA (Hololive Ukraine) Chat\" створені виключно для українців (13+). В них можуть знаходитись тільки люди які: \n- Народились в Україні, та проживають, на данний момент, у ній.\n- Народились за межами України, але проживають у ній.\n- Народились в Україні але, на даний момент, не проживають у ній.\n\"HoloUA (Hololive Ukraine) Chat\" відкритий для усіх українців. Щоб потрапити до нього, заповніть, будь ласка, анкету, та дочекайтесь, поки її схвалять адміни.\nУ \"HoloKyiv Chat\" можна потрапити тільки особисто, якщо ви проживаєте у Київі, або є близьким другом одного із учасників чату. Із приводу додавання до чату пишіть @Chirkopol у приватні повідомлення.\n🔨 Якщо у процесі спілкування виявиться, що ви не українець, вас буде видалено із чату, до моменту, поки ви їм не станете. Без образ. Ми створюємо виключно українське ком'юніті.",
"2⃣) Заборонено поширення NSFW-контенту з прямим або частково прихованим порнографічним змістом. На контенті \"еротичного характеру\" повинні бути закриті \"сумнівні\" ділянки тіл. \nЗаборонено поширення шок-контенту з великою наявністю крові та/або фізичних пошкоджень.", "2⃣) Заборонено поширення NSFW-контенту з прямим або частково прихованим порнографічним змістом. На контенті \"еротичного характеру\" повинні бути закриті \"сумнівні\" ділянки тіл. \nЗаборонено поширення шок-контенту з великою наявністю крові та/або фізичних пошкоджень.",
@@ -292,7 +280,6 @@
"applications": "Отримати всі анкети як JSON", "applications": "Отримати всі анкети як JSON",
"cancel": "Відмінити актуальну дію", "cancel": "Відмінити актуальну дію",
"identify": "Дізнатись дані про користувача за айді", "identify": "Дізнатись дані про користувача за айді",
"issue": "Задачі для покращення бота",
"label": "Встановити нікнейм користувачу", "label": "Встановити нікнейм користувачу",
"message": "Надіслати користувачу повідомлення", "message": "Надіслати користувачу повідомлення",
"nearby": "Показати користувачів поблизу", "nearby": "Показати користувачів поблизу",

View File

@@ -21,15 +21,8 @@ async def callback_reapply_query_accept(app: Client, clb: CallbackQuery):
await app.send_message(holo_user.id, locale("approved_joined", "message", locale=holo_user)) await app.send_message(holo_user.id, locale("approved_joined", "message", locale=holo_user))
applications = col_applications.find({"user": holo_user.id}) col_applications.delete_one({"user": holo_user.id})
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
if len(list(applications)) > 1:
col_applications.delete_many({"user": holo_user.id})
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
elif applications == 1:
col_applications.find_one_and_replace({"user": holo_user.id}, {"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
else:
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"state": "approved", "sent": False}}) col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"state": "approved", "sent": False}})
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]] edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
@@ -83,30 +76,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

@@ -68,6 +68,23 @@ async def callback_query_reject(app: Client, clb: CallbackQuery):
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup)) await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sub_rejected", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True) await clb.answer(text=locale("sub_rejected", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
@app.on_callback_query(filters.regex("sub_aggressive_[\s\S]*"))
async def callback_query_reject_aggressive(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin", "groups"), locale("rejected_by_agr", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
await app.send_message(holo_user.id, locale("rejected_aggressive", "message", locale=holo_user))
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id} due to being aggressive")
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sub_aggressive", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
@app.on_callback_query(filters.regex("sub_russian_[\s\S]*")) @app.on_callback_query(filters.regex("sub_russian_[\s\S]*"))
async def callback_query_reject_russian(app: Client, clb: CallbackQuery): async def callback_query_reject_russian(app: Client, clb: CallbackQuery):

View File

@@ -3,17 +3,14 @@ from pyrogram import filters
from pyrogram.types import Message, ReplyKeyboardRemove from pyrogram.types import Message, ReplyKeyboardRemove
from pyrogram.client import Client from pyrogram.client import Client
from modules.utils import should_quote, logWrite, locale from modules.utils import should_quote, logWrite, locale
from modules.database import col_tmp, col_spoilers, col_applications from modules.database import col_tmp, col_spoilers
from modules import custom_filters from modules import custom_filters
# Cancel command =============================================================================================================== # Cancel command ===============================================================================================================
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("cancel", prefixes=["/"])) @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): async def command_cancel(app: Client, msg: Message):
col_tmp.delete_many( {"user": msg.from_user.id, "sent": False} ) col_tmp.delete_many( {"user": msg.from_user.id} )
col_spoilers.delete_many( {"user": msg.from_user.id, "completed": False} ) col_spoilers.delete_many( {"user": msg.from_user.id, "completed": False} )
if col_applications.find_one( {"user": msg.from_user.id} ) is None: await msg.reply_text(locale("cancel", "message", locale=msg.from_user), quote=should_quote(msg), reply_markup=ReplyKeyboardRemove())
await msg.reply_text(locale("cancel_reapply", "message", locale=msg.from_user), quote=should_quote(msg), reply_markup=ReplyKeyboardRemove())
else:
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}") logWrite(f"Cancelling all ongoing tmp operations for {msg.from_user.id}")
# ============================================================================================================================== # ==============================================================================================================================

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

@@ -1,21 +0,0 @@
from typing import Union
from app import app
from pyrogram import filters
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, User, Message
from pyrogram.client import Client
from modules.utils import configGet, locale
from modules import custom_filters
from classes.holo_user import HoloUser
# Issue command ================================================================================================================
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["issue"], prefixes=["/"]))
async def cmd_issue(app: Client, msg: Message):
await msg.reply_text(locale("issue", "message", locale=msg.from_user), disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("issue", "button", locale=msg.from_user), url=configGet("issues"))
]
]
))
# ==============================================================================================================================

View File

@@ -3,10 +3,9 @@ from pyrogram import filters
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
from pyrogram.client import Client from pyrogram.client import Client
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
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,44 +26,23 @@ 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.application_state()[1] is True and holo_user.application_state()[0] not in ["fill", "rejected"]):
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)
await welcome_pass(app, msg, once_again=True)
else:
if holo_user.sponsorship_state()[0] == "fill": if holo_user.sponsorship_state()[0] == "fill":
await msg.reply_text(locale("finish_sponsorship", "message"), quote=should_quote(msg)) await msg.reply_text(locale("finish_sponsorship", "message"), quote=should_quote(msg))
return return
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:
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: else:
await msg.reply_text(locale("reapply_in_progress", "message", locale=holo_user).format(locale("confirm", "keyboard", locale=holo_user)[1][0]), reply_markup=InlineKeyboardMarkup([ await msg.reply_text(locale("reapply_in_progress", "message", locale=holo_user).format(locale("confirm", "keyboard", locale=holo_user)[1][0]), reply_markup=InlineKeyboardMarkup([

View File

@@ -24,35 +24,42 @@ async def cmd_resetcommands(app: Client, msg: Message):
if entry.endswith(".json"): if entry.endswith(".json"):
valid_locales.append(".".join(entry.split(".")[:-1])) valid_locales.append(".".join(entry.split(".")[:-1]))
logWrite(f'Resetting commands in groups {configGet("admin", "groups")} and {configGet("users", "groups")}', debug=True) if configGet("debug") is True:
logWrite(f'Resetting commands in groups {configGet("admin", "groups")} and {configGet("users", "groups")}')
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("admin", "groups"))) await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")))
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("users", "groups"))) await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("users", "groups")))
for admin in configGet("admins"): for admin in configGet("admins"):
try: try:
logWrite(f'Resetting commands for admin {admin}', debug=True) if configGet("debug") is True:
logWrite(f'Resetting commands for admin {admin}')
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=admin)) await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=admin))
except bad_request_400.PeerIdInvalid: except bad_request_400.PeerIdInvalid:
pass pass
try: try:
logWrite(f'Resetting commands for owner {configGet("owner")}', debug=True) if configGet("debug") is True:
logWrite(f'Resetting commands for owner {configGet("owner")}')
for lc in valid_locales: for lc in valid_locales:
logWrite(f'Resetting commands for owner {configGet("owner")} [{lc}]', debug=True) if configGet("debug") is True:
logWrite(f'Resetting commands for owner {configGet("owner")} [{lc}]')
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")), language_code=lc) await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")), language_code=lc)
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner"))) await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")))
except bad_request_400.PeerIdInvalid: except bad_request_400.PeerIdInvalid:
pass pass
for lc in valid_locales: for lc in valid_locales:
logWrite(f'Resetting commands for locale {lc}', debug=True) if configGet("debug") is True:
logWrite(f'Resetting commands for locale {lc}')
await app.delete_bot_commands(scope=BotCommandScopeDefault(), language_code=lc) await app.delete_bot_commands(scope=BotCommandScopeDefault(), language_code=lc)
logWrite(f'Resetting default commands', debug=True) if configGet("debug") is True:
logWrite(f'Resetting default commands')
await app.delete_bot_commands() await app.delete_bot_commands()
await msg.reply_text("OK", quote=should_quote(msg)) await msg.reply_text("OK", quote=should_quote(msg))
logWrite(str(await app.get_bot_commands()), debug=True) if configGet("debug") is True:
logWrite(str(await app.get_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")))), debug=True) logWrite(str(await app.get_bot_commands()))
logWrite(str(await app.get_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")))))
# ============================================================================================================================== # ==============================================================================================================================

View File

@@ -6,11 +6,11 @@ from classes.errors.holo_user import UserNotFoundError, UserInvalidError
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
from modules.logging import logWrite from modules.logging import logWrite
from modules.utils import locale from modules.utils import locale
from modules.database import col_spoilers, col_applications 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 & ~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:
@@ -18,24 +18,18 @@ async def cmd_spoiler(app: Client, msg: Message):
except (UserInvalidError, UserNotFoundError): except (UserInvalidError, UserNotFoundError):
return return
if col_applications.find_one( {"user": holo_user.id} ) is None:
await msg.reply_text(locale("not_member", "message", locale=msg.from_user))
return
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 col_spoilers.find_one( {"user": holo_user.id, "completed": False} ) is None: if col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} ) is None:
col_spoilers.insert_one( col_spoilers.insert_one(
{ {
"user": holo_user.id, "user": msg.from_user.id,
"completed": False, "completed": False,
"category": None, "category": None,
"description": None, "description": None,
"photo": None, "photo": None,
"video": None, "video": None,
"audio": None,
"animation": None, "animation": None,
"document": None, "document": None,
"caption": None, "caption": None,

View File

@@ -33,15 +33,13 @@ async def cmd_start(app: Client, msg: Message):
try: try:
spoiler = col_spoilers.find_one( {"_id": ObjectId(msg.command[1])} ) spoiler = col_spoilers.find_one( {"_id": ObjectId(msg.command[1])} )
if spoiler["photo"] is not None: if spoiler["photo"] is not None:
await msg.reply_cached_media(spoiler["photo"], caption=spoiler["caption"]) await msg.reply_document(spoiler["photo"], caption=spoiler["caption"])
if spoiler["video"] is not None: if spoiler["video"] is not None:
await msg.reply_cached_media(spoiler["video"], caption=spoiler["caption"]) await msg.reply_cached_media(spoiler["video"], caption=spoiler["caption"])
if spoiler["audio"] is not None:
await msg.reply_cached_media(spoiler["audio"], caption=spoiler["caption"])
if spoiler["animation"] is not None: if spoiler["animation"] is not None:
await msg.reply_cached_media(spoiler["animation"], caption=spoiler["caption"]) await msg.reply_cached_media(spoiler["animation"], caption=spoiler["caption"])
if spoiler["document"] is not None: if spoiler["document"] is not None:
await msg.reply_cached_media(spoiler["document"], caption=spoiler["caption"]) await msg.reply_document(spoiler["document"], caption=spoiler["caption"])
if spoiler["text"] is not None: if spoiler["text"] is not None:
await msg.reply_text(spoiler["text"]) await msg.reply_text(spoiler["text"])
except InvalidId: except InvalidId:

View File

@@ -15,11 +15,7 @@ async def member_func(_, __, msg: Message):
return True if (msg.from_user.id in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))) else False return True if (msg.from_user.id in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))) else False
async def allowed_func(_, __, msg: Message): async def allowed_func(_, __, msg: Message):
output = False return True if (col_applications.find_one({"user": msg.from_user.id}) is not None) else False
output = True if (col_applications.find_one({"user": msg.from_user.id}) is not None) else False
if path.exists(path.join(configGet("cache", "locations"), "group_members")) and (msg.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))):
output = False
return output
async def enabled_general_func(_, __, msg: Message): async def enabled_general_func(_, __, msg: Message):
return configGet("enabled", "features", "general") return configGet("enabled", "features", "general")
@@ -39,9 +35,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 +48,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

@@ -9,7 +9,7 @@ from pyrogram.enums.parse_mode import ParseMode
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
from modules.utils import all_locales, configGet, locale, logWrite from modules.utils import all_locales, configGet, locale, logWrite
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
# Confirmation ================================================================================================================= # Confirmation =================================================================================================================
@@ -54,12 +54,8 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
i += 1 i += 1
if tmp_application["reapply"] is True and col_applications.find_one({"user": holo_user.id}) is not None: if tmp_application["reapply"]:
await app.send_message( await app.send_message(chat_id=configGet("admin", "groups"), 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(
chat_id=configGet("admin", "groups"),
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}") InlineKeyboardButton(text=str(locale("reapply_yes", "button")), callback_data=f"reapply_yes_{holo_user.id}")
@@ -71,11 +67,7 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
) )
) )
else: else:
await app.send_message( await app.send_message(chat_id=configGet("admin", "groups"), 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(
chat_id=configGet("admin", "groups"),
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}") InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}")
@@ -83,6 +75,9 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
[ [
InlineKeyboardButton(text=str(locale("sub_no", "button")), callback_data=f"sub_no_{holo_user.id}") InlineKeyboardButton(text=str(locale("sub_no", "button")), callback_data=f"sub_no_{holo_user.id}")
], ],
[
InlineKeyboardButton(text=str(locale("sub_aggressive", "button")), callback_data=f"sub_aggressive_{holo_user.id}")
],
[ [
InlineKeyboardButton(text=str(locale("sub_russian", "button")), callback_data=f"sub_russian_{holo_user.id}") InlineKeyboardButton(text=str(locale("sub_russian", "button")), callback_data=f"sub_russian_{holo_user.id}")
] ]
@@ -122,7 +117,7 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
else: else:
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}") sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}")
await app.send_cached_media(configGet("admin", "groups"), tmp_sponsorship["sponsorship"]["proof"], 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( await app.send_cached_media(chat_id=configGet("admin", "groups"), photo=tmp_sponsorship["sponsorship"]["proof"], 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_yes", "button")), callback_data=f"sponsor_yes_{holo_user.id}")

View File

@@ -1,7 +1,6 @@
from traceback import print_exc from traceback import print_exc
from app import app, isAnAdmin from app import app, isAnAdmin
import asyncio import asyncio
from ftfy import fix_text
from pyrogram import filters from pyrogram import filters
from pyrogram.types import Message, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton from pyrogram.types import Message, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton
from pyrogram.client import Client from pyrogram.client import Client
@@ -22,7 +21,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 +51,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 +65,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:
@@ -96,19 +89,14 @@ async def any_stage(app: Client, msg: Message):
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))) 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 return
if spoiler["description"] is None and (spoiler["photo"] is None and spoiler["video"] is None and spoiler["audio"] is None and spoiler["animation"] is None and spoiler["text"] is None): 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"): # for lc in all_locales("spoiler_description", "keyboard"):
# if msg.text == lc[-1][0]: # 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))) # 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 # return
if msg.text != "-": if msg.text != "-":
msg.text = fix_text(msg.text)
if len(msg.text) > 1024:
await msg.reply_text(locale("spoiler_description_too_long", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
return
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text}} ) col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text}} )
else: else:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": ""}} ) col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": ""}} )
@@ -127,12 +115,7 @@ async def any_stage(app: Client, msg: Message):
if msg.video is not None: 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, "caption": msg.caption, "completed": True}} ) 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 audio with id {msg.video.file_id} to {msg.from_user.id}'s spoiler") logWrite(f"Adding video with id {msg.video.file_id} to {msg.from_user.id}'s spoiler")
ready = True
if msg.audio is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"audio": msg.audio.file_id, "caption": msg.caption, "completed": True}} )
logWrite(f"Adding video with id {msg.audio.file_id} to {msg.from_user.id}'s spoiler")
ready = True ready = True
if msg.animation is not None: if msg.animation is not None:
@@ -145,44 +128,14 @@ async def any_stage(app: Client, msg: Message):
logWrite(f"Adding document with id {msg.document.file_id} to {msg.from_user.id}'s spoiler") logWrite(f"Adding document with id {msg.document.file_id} to {msg.from_user.id}'s spoiler")
ready = True ready = True
if spoiler["photo"] is None and spoiler["video"] is None and spoiler["audio"] is None and spoiler["animation"] is None and spoiler["document"] is None and spoiler["text"] is None: if spoiler["photo"] is None and spoiler["video"] is None and spoiler["animation"] is None and spoiler["document"] is None and spoiler["text"] is None:
if msg.text is not None: 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}} ) 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") logWrite(f"Adding text '{msg.text}' to {msg.from_user.id}'s spoiler")
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

@@ -1,13 +1,10 @@
from datetime import datetime
from app import app, isAnAdmin from app import app, isAnAdmin
from pyrogram.types import ChatPermissions, InlineKeyboardMarkup, InlineKeyboardButton, ChatMemberUpdated from pyrogram.types import ChatPermissions, InlineKeyboardMarkup, InlineKeyboardButton, ChatMemberUpdated
from pyrogram.client import Client from pyrogram.client import Client
from modules.utils import configGet, locale from modules.utils import configGet, locale
from modules import custom_filters
from modules.logging import logWrite from modules.logging import logWrite
from modules.database import col_applications
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
from dateutil.relativedelta import relativedelta from modules import custom_filters
# Filter users on join ========================================================================================================= # Filter users on join =========================================================================================================
@app.on_chat_member_updated(custom_filters.enabled_invites_check, group=configGet("users", "groups")) @app.on_chat_member_updated(custom_filters.enabled_invites_check, group=configGet("users", "groups"))
@@ -19,61 +16,11 @@ async def filter_join(app: Client, member: ChatMemberUpdated):
holo_user = HoloUser(member.from_user) holo_user = HoloUser(member.from_user)
if (holo_user.link is not None) and (holo_user.link == member.invite_link.invite_link): if (holo_user.link is not None) and (holo_user.link == member.invite_link.invite_link):
logWrite(f"User {holo_user.id} joined destination group with correct link {holo_user.link}") logWrite(f"User {holo_user.id} joined destination group with correct link {holo_user.link}")
application = col_applications.find_one({"user": holo_user.id})
application_content = []
i = 1
for question in application['application']:
if i == 2:
age = relativedelta(datetime.now(), application['application']['2'])
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
elif i == 3:
if application['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']}")
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application'][question]}")
i += 1
await app.send_message(configGet("users", "groups"), locale("joined_application", "messages").format(member.from_user.first_name, member.from_user.username, "\n".join(application_content)))
return return
if await isAnAdmin(member.invite_link.creator.id): if await isAnAdmin(member.invite_link.creator.id):
logWrite(f"User {holo_user.id} joined destination group with link {holo_user.link} of an admin {member.invite_link.creator.id}") logWrite(f"User {holo_user.id} joined destination group with link {holo_user.link} of an admin {member.invite_link.creator.id}")
application = col_applications.find_one({"user": holo_user.id})
if application is None:
return
application_content = []
i = 1
for question in application['application']:
if i == 2:
age = relativedelta(datetime.now(), application['application']['2'])
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
elif i == 3:
if application['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']}")
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application'][question]}")
i += 1
await app.send_message(configGet("users", "groups"), locale("joined_application", "messages").format(member.from_user.first_name, member.from_user.username, "\n".join(application_content)))
return return
logWrite(f"User {holo_user.id} joined destination group with stolen/unapproved link {holo_user.link}") logWrite(f"User {holo_user.id} joined destination group with stolen/unapproved link {holo_user.link}")

View File

@@ -13,7 +13,7 @@ for pattern in all_locales("welcome", "keyboard"):
for pattern in all_locales("return", "keyboard"): for pattern in all_locales("return", "keyboard"):
welcome_1.append(pattern[0][0]) welcome_1.append(pattern[0][0])
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(welcome_1, prefixes=[""])) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(welcome_1, prefixes=[""]))
async def welcome_pass(app: Client, msg: Message, once_again: bool = False) -> None: async def welcome_pass(app: Client, msg: Message, once_again: bool = True) -> None:
"""Set user's stage to 1 and start a fresh application """Set user's stage to 1 and start a fresh application
### Args: ### Args:
@@ -27,13 +27,9 @@ async def welcome_pass(app: Client, msg: Message, once_again: bool = False) -> N
holo_user = HoloUser(msg.from_user) holo_user = HoloUser(msg.from_user)
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

@@ -11,8 +11,7 @@ from pyrogram.enums.chat_members_filter import ChatMembersFilter
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from classes.errors.holo_user import UserNotFoundError, UserInvalidError from classes.errors.holo_user import UserNotFoundError, UserInvalidError
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
from modules.logging import logWrite from modules.utils import configGet, locale
from modules.utils import configGet, jsonLoad, locale
from modules.database import col_applications, col_spoilers from modules.database import col_applications, col_spoilers
from bson.objectid import ObjectId from bson.objectid import ObjectId
from bson.errors import InvalidId from bson.errors import InvalidId
@@ -22,36 +21,34 @@ 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:
spoil = col_spoilers.find_one( {"_id": ObjectId(inline_query.query.removeprefix("spoiler:"))} ) spoil = col_spoilers.find_one( {"_id": ObjectId(inline_query.query.removeprefix("spoiler:"))} )
if spoil is not None: if spoil is not None:
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"]) 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 = [ results = [
InlineQueryResultArticle( InlineQueryResultArticle(
title=locale("title", "inline", "spoiler", locale=inline_query.from_user), title=locale("title", "inline", "spoiler", locale=inline_query.from_user),
description=locale("description", "inline", "spoiler", locale=inline_query.from_user), description=locale("description", "inline", "spoiler", locale=inline_query.from_user),
input_message_content=InputTextMessageContent(desc, disable_web_page_preview=True), input_message_content=InputTextMessageContent(desc, disable_web_page_preview=True),
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=inline_query.from_user), callback_data=f'sid_{inline_query.query.removeprefix("spoiler:")}')]]) reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=inline_query.from_user), callback_data=f'sid_{inline_query.query.removeprefix("spoiler:")}')]])
) )
] ]
except InvalidId: except InvalidId:
results = [] results = []
await inline_query.answer( await inline_query.answer(
results=results results=results
) )
return return
if inline_query.chat_type in [ChatType.CHANNEL]: if inline_query.chat_type in [ChatType.CHANNEL]:
await inline_query.answer( await inline_query.answer(
@@ -67,33 +64,22 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
) )
return return
results_forbidden = [
InlineQueryResultArticle(
title=locale("title", "inline", "forbidden", locale=inline_query.from_user),
input_message_content=InputTextMessageContent(
locale("message_content", "inline", "forbidden", locale=inline_query.from_user)
),
description=locale("description", "inline", "forbidden", locale=inline_query.from_user)
)
]
try: try:
holo_user = HoloUser(inline_query.from_user) holo_user = HoloUser(inline_query.from_user)
except (UserNotFoundError, UserInvalidError): except (UserNotFoundError, UserInvalidError):
logWrite(f"Could not find application of {inline_query.from_user.id}, ignoring inline query", debug=True)
await inline_query.answer( await inline_query.answer(
results=results_forbidden results=[
InlineQueryResultArticle(
title=locale("title", "inline", "forbidden", locale=inline_query.from_user),
input_message_content=InputTextMessageContent(
locale("message_content", "inline", "forbidden", locale=inline_query.from_user)
),
description=locale("description", "inline", "forbidden", locale=inline_query.from_user)
)
]
) )
return return
if path.exists(path.join(configGet("cache", "locations"), "group_members")) and (inline_query.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))):
if path.exists(path.join(configGet("cache", "locations"), "admins")) and (inline_query.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "admins"))):
logWrite(f"{inline_query.from_user.id} is not an admin and not in members group, ignoring inline query", debug=True)
await inline_query.answer(
results=results_forbidden
)
return
if holo_user.application_approved() or (await isAnAdmin(holo_user.id) is True): if holo_user.application_approved() or (await isAnAdmin(holo_user.id) is True):
max_results = configGet("inline_preview_count") if inline_query.query != "" else 200 max_results = configGet("inline_preview_count") if inline_query.query != "" else 200
@@ -175,6 +161,5 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
await inline_query.answer( await inline_query.answer(
results=results, results=results,
cache_time=10, cache_time=10
is_personal=True )
)

View File

@@ -1,22 +1,18 @@
"""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
from app import app from app import app
from pyrogram.types import BotCommand, BotCommandScopeChat, BotCommandScopeChatAdministrators from pyrogram.types import BotCommand, BotCommandScopeChat
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()
@@ -26,10 +22,8 @@ if configGet("enabled", "scheduler", "cache_members"):
list_of_users = [] list_of_users = []
async for member in app.get_chat_members(configGet("users", "groups")): async for member in app.get_chat_members(configGet("users", "groups")):
list_of_users.append(member.user.id) list_of_users.append(member.user.id)
makedirs(configGet("cache", "locations"), exist_ok=True) makedirs("cache", exist_ok=True)
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "group_members")) jsonSave(list_of_users, path.join(configGet("cache", "locations"), "group_members"))
if configGet("debug") is True:
logWrite("User group caching performed", debug=True)
if configGet("enabled", "scheduler", "cache_admins"): if configGet("enabled", "scheduler", "cache_admins"):
@scheduler.scheduled_job(trigger="interval", seconds=configGet("interval", "scheduler", "cache_admins")) @scheduler.scheduled_job(trigger="interval", seconds=configGet("interval", "scheduler", "cache_admins"))
@@ -37,14 +31,12 @@ if configGet("enabled", "scheduler", "cache_admins"):
list_of_users = [] list_of_users = []
async for member in app.get_chat_members(configGet("admin", "groups")): async for member in app.get_chat_members(configGet("admin", "groups")):
list_of_users.append(member.user.id) list_of_users.append(member.user.id)
makedirs(configGet("cache", "locations"), exist_ok=True) makedirs("cache", exist_ok=True)
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "admins")) jsonSave(list_of_users, path.join(configGet("cache", "locations"), "admins"))
if configGet("debug") is True:
logWrite("Admin group caching performed", debug=True)
# Cache the avatars of group members # Cache the avatars of group members
if configGet("enabled", "scheduler", "cache_avatars"): if configGet("enabled", "scheduler", "cache_avatars"):
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=15)) @scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=10))
@scheduler.scheduled_job(trigger="interval", hours=configGet("interval", "scheduler", "cache_avatars")) @scheduler.scheduled_job(trigger="interval", hours=configGet("interval", "scheduler", "cache_avatars"))
async def cache_avatars(): async def cache_avatars():
list_of_users = [] list_of_users = []
@@ -66,8 +58,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,26 +74,22 @@ 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 = abs(relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days)+1 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, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore
logWrite(f"Notified user {entry['user']} that sponsorship expires in {until_expiry} days") logWrite(f"Notified user that sponsorship expires in {until_expiry} days")
except Exception as exp: except Exception as exp:
logWrite(f"Could not find user {entry['user']} notify about sponsorship expiry due to '{exp}'") logWrite(f"Could not find user {entry['user']} notify about sponsorship expiry due to '{exp}'")
continue continue
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 {entry['user']} that sponsorship expired") logWrite(f"Notified user that sponsorship expired")
except Exception as exp: except Exception as exp:
logWrite(f"Could not find user {entry['user']} notify about sponsorship expired due to '{exp}'") logWrite(f"Could not find user {entry['user']} notify about sponsorship expired due to '{exp}'")
except Exception as exp: except Exception as exp:
@@ -113,7 +99,7 @@ if configGet("enabled", "features", "sponsorships") is True:
# Register all bot commands # Register all bot commands
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=10)) @scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=3))
async def commands_register(): async def commands_register():
commands = { commands = {
@@ -122,7 +108,6 @@ async def commands_register():
"owner": [], "owner": [],
"group_users": [], "group_users": [],
"group_admins": [], "group_admins": [],
"group_users_admins": [],
"locales": {} "locales": {}
} }
@@ -132,7 +117,6 @@ async def commands_register():
"owner": [], "owner": [],
"group_users": [], "group_users": [],
"group_admins": [], "group_admins": [],
"group_users_admins": [],
"locales": {} "locales": {}
} }
@@ -147,8 +131,7 @@ async def commands_register():
"admins": [], "admins": [],
"owner": [], "owner": [],
"group_users": [], "group_users": [],
"group_admins": [], "group_admins": []
"group_users_admins": []
} }
if configGet("debug") is True: if configGet("debug") is True:
commands_raw["locales"][".".join(entry.split(".")[:-1])] = { commands_raw["locales"][".".join(entry.split(".")[:-1])] = {
@@ -156,8 +139,7 @@ async def commands_register():
"admins": [], "admins": [],
"owner": [], "owner": [],
"group_users": [], "group_users": [],
"group_admins": [], "group_admins": []
"group_users_admins": []
} }
config_modules = configGet("features") config_modules = configGet("features")
@@ -173,7 +155,8 @@ async def commands_register():
enabled = True enabled = True
if enabled is False: if enabled is False:
logWrite(f"Not registering {command} at all", debug=True) if configGet("debug") is True:
logWrite(f"Not registering {command} at all")
continue continue
for permission in config_commands[command]["permissions"]: for permission in config_commands[command]["permissions"]:
@@ -233,40 +216,7 @@ async def commands_register():
except bad_request_400.ChannelInvalid: except bad_request_400.ChannelInvalid:
logWrite(f"Could not register commands for destination group. Bot is likely not in the group.") logWrite(f"Could not register commands for destination group. Bot is likely not in the group.")
# Registering destination group admin commands
try:
await app.set_bot_commands(commands["group_users_admins"], scope=BotCommandScopeChatAdministrators(chat_id=configGet("users", "groups")))
logWrite("Registered destination group admin commands")
except bad_request_400.ChannelInvalid:
logWrite(f"Could not register admin commands for destination group. Bot is likely not in the group.")
if configGet("debug") is True: 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)}")
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

@@ -1,12 +1,10 @@
APScheduler==3.9.1.post1 APScheduler==3.9.1.post1
fastapi~=0.88.0 fastapi==0.88.0
psutil==5.9.4 psutil==5.9.4
pymongo==4.3.3 pymongo==4.3.3
Pyrogram~=2.0.97 Pyrogram~=2.0.93
requests==2.28.2 requests==2.28.1
tgcrypto==1.2.5 tgcrypto==1.2.5
python_dateutil==2.8.2 python_dateutil==2.8.2
starlette~=0.22.0 starlette==0.23.0
ujson~=5.7.0 ujson==5.6.0
ftfy~=6.1.1
xmltodict~=0.13.0

View File

@@ -7,7 +7,6 @@
"description", "description",
"photo", "photo",
"video", "video",
"audio",
"animation", "animation",
"document", "document",
"caption", "caption",
@@ -39,10 +38,6 @@
"bsonType": ["string", "null"], "bsonType": ["string", "null"],
"description": "Spoilered video" "description": "Spoilered video"
}, },
"audio": {
"bsonType": ["string", "null"],
"description": "Spoilered audio"
},
"animation": { "animation": {
"bsonType": ["string", "null"], "bsonType": ["string", "null"],
"description": "Spoilered animation/GIF" "description": "Spoilered animation/GIF"