Merge pull request 'Spoilers, major command system improvements' (#4) from dev into master

Reviewed-on: profitroll/HoloCheckerBot#4
This commit is contained in:
Profitroll 2023-01-05 13:45:14 +02:00
commit 68c7cc0ada
39 changed files with 1002 additions and 326 deletions

200
README.md
View File

@ -32,14 +32,16 @@ You can see config file with all the comments below:
"locale": "uk", "locale": "uk",
"debug": false, "debug": false,
"owner": 0, "owner": 0,
"bot_id": 0,
"age_allowed": 0, "age_allowed": 0,
"api": "http://example.com", "api": "http://example.com",
"inline_preview_count": 7, "inline_preview_count": 7,
"admin_group": 0,
"destination_group": 0,
"remove_application_time": -1, "remove_application_time": -1,
"search_radius": 50,
"admins": [], "admins": [],
"groups": {
"admin": 0,
"users": 0
},
"bot": { "bot": {
"api_id": 0, "api_id": 0,
"api_hash": "", "api_hash": "",
@ -59,6 +61,29 @@ You can see config file with all the comments below:
"size": 512, "size": 512,
"location": "logs" "location": "logs"
}, },
"features": {
"general": {
"enabled": true
},
"applications": {
"enabled": true
},
"sponsorships": {
"enabled": true
},
"warnings": {
"enabled": true
},
"invites_check": {
"enabled": true
},
"dinovoice": {
"enabled": false
},
"spoilers": {
"enabled": true
}
},
"scheduler": { "scheduler": {
"birthdays": { "birthdays": {
"time": 9, "time": 9,
@ -67,6 +92,18 @@ You can see config file with all the comments below:
"sponsorships": { "sponsorships": {
"time": 9, "time": 9,
"enabled": true "enabled": true
},
"cache_avatars": {
"interval": 6,
"enabled": true
},
"cache_members": {
"interval": 30,
"enabled": true
},
"cache_admins": {
"interval": 120,
"enabled": true
} }
}, },
"locations": { "locations": {
@ -74,28 +111,134 @@ You can see config file with all the comments below:
"locale": "locale" "locale": "locale"
}, },
"commands": { "commands": {
"rules": "Check out the rules", "rules": {
"reapply": "Resubmit the application", "permissions": [
"sponsorship": "Apply for sponsor role" "users",
}, "admins"
"commands_admin": { ],
"reboot": "Restart the bot", "modules": [
"message": "Send a message", "general"
"label": "Set user's nickname", ]
"warnings": "Check user's warnings", },
"application": "Check user's application", "spoiler": {
"applications": "Retrieve all applications as a JSON" "permissions": [
}, "users",
"commands_group_admin": { "admins"
"reboot": "Restart the bot", ],
"message": "Send a message", "modules": [
"label": "Set user's nickname", "spoilers"
"warnings": "Check user's warnings", ]
"application": "Check user's application", },
"applications": "Retrieve all applications as a JSON" "cancel": {
}, "permissions": [
"commands_group_destination": { "users",
"warn": "Warn a user" "admins"
],
"modules": [
"spoilers",
"applications",
"sponsorships"
]
},
"nearby": {
"permissions": [
"users",
"admins",
"group_users",
"group_admins"
],
"modules": [
"applications"
]
},
"warn": {
"permissions": [
"group_users"
],
"modules": [
"warnings"
]
},
"reapply": {
"permissions": [
"users",
"admins"
],
"modules": [
"applications"
]
},
"sponsorship": {
"permissions": [
"users",
"admins"
],
"modules": [
"sponsorships"
]
},
"reboot": {
"permissions": [
"owner"
],
"modules": [
"general"
]
},
"label": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"applications"
]
},
"message": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"general"
]
},
"identify": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"applications",
"sponsorships"
]
},
"application": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"applications"
]
},
"applications": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"applications"
]
},
"resetcommands": {
"permissions": [
"owner"
],
"modules": [
"general"
]
}
} }
} }
``` ```
@ -104,9 +247,10 @@ After all of that you're good to go! Happy using :)
## To-Do ## To-Do
* [x] Check sponsorship on Holo girls * [ ] Stats and infographics
* [ ] Stats and infographic
* [x] /nearby command
* [ ] Check group members without completed application * [ ] Check group members without completed application
* [x] Replicate some functions of @spoilerobot
* [x] Check sponsorship on Holo girls
* [x] /nearby command
* [x] Complete messenger between user and admins * [x] Complete messenger between user and admins
* [x] Get application by id and user_id * [x] Get application by id and user_id

2
app.py
View File

@ -22,7 +22,7 @@ async def isAnAdmin(admin_id):
# Check if user is in admin group # Check if user is in admin group
try: try:
async for member in app.get_chat_members(configGet("admin_group")): async for member in app.get_chat_members(configGet("admin", "groups")):
if member.user.id == admin_id: if member.user.id == admin_id:
return True return True
except bad_request_400.ChannelInvalid: except bad_request_400.ChannelInvalid:

View File

@ -6,7 +6,7 @@ from pyrogram.types import User, ChatMember, ChatPrivileges, Chat, Message, Phot
from pyrogram.errors import bad_request_400 from pyrogram.errors import bad_request_400
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from classes.errors.geo import PlaceNotFoundError from classes.errors.geo import PlaceNotFoundError
from modules.database import col_tmp, col_users, col_applications, col_sponsorships, col_messages from modules.database import col_tmp, col_users, col_applications, col_sponsorships, col_messages, col_spoilers
from modules.logging import logWrite from modules.logging import logWrite
from modules.utils import configGet, create_tmp, download_tmp, find_location, locale, should_quote from modules.utils import configGet, create_tmp, download_tmp, find_location, locale, should_quote
@ -284,9 +284,9 @@ class HoloUser():
raise LabelTooLongError(label) raise LabelTooLongError(label)
self.label = label self.label = label
try: try:
await app.promote_chat_member(configGet("destination_group"), 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 app.set_administrator_title(configGet("destination_group"), self.id, label) await app.set_administrator_title(configGet("users", "groups"), self.id, label)
self.set("label", label) self.set("label", label)
except bad_request_400.UserCreator: except bad_request_400.UserCreator:
logWrite(f"Could not set {self.id}'s title to '{self.label}' because of bad_request_400.UserCreator") logWrite(f"Could not set {self.id}'s title to '{self.label}' because of bad_request_400.UserCreator")
@ -301,9 +301,9 @@ class HoloUser():
""" """
self.label = "" self.label = ""
self.set("label", "") self.set("label", "")
await app.set_administrator_title(configGet("destination_group"), self.id, "") await app.set_administrator_title(configGet("users", "groups"), self.id, "")
if not await isAnAdmin(self.id): if not await isAnAdmin(self.id):
await app.promote_chat_member(configGet("destination_group"), self.id, privileges=ChatPrivileges( await app.promote_chat_member(configGet("users", "groups"), self.id, privileges=ChatPrivileges(
can_manage_chat=False, can_manage_chat=False,
can_pin_messages=False, can_pin_messages=False,
can_manage_video_chats=False can_manage_video_chats=False
@ -351,6 +351,9 @@ class HoloUser():
if self.sponsorship_state()[0] == "fill": if self.sponsorship_state()[0] == "fill":
return return
if self.spoiler_state() is True:
return
# col_tmp.insert_one( # col_tmp.insert_one(
# document=DefaultApplicationTemp(self.id).dict # document=DefaultApplicationTemp(self.id).dict
# ) # )
@ -545,3 +548,11 @@ class HoloUser():
else: else:
return return
def spoiler_state(self) -> bool:
"""Check if user has any started but not finished spoilers
### Returns:
* `bool`: `True` if any not finished spoilers available and `False` if none.
"""
return False if col_spoilers.find_one({"user": self.id, "completed": False}) is None else True

View File

@ -2,15 +2,16 @@
"locale": "uk", "locale": "uk",
"debug": false, "debug": false,
"owner": 0, "owner": 0,
"bot_id": 0,
"age_allowed": 0, "age_allowed": 0,
"api": "http://example.com", "api": "http://example.com",
"inline_preview_count": 7, "inline_preview_count": 7,
"admin_group": 0,
"destination_group": 0,
"remove_application_time": -1, "remove_application_time": -1,
"search_radius": 50, "search_radius": 50,
"admins": [], "admins": [],
"groups": {
"admin": 0,
"users": 0
},
"bot": { "bot": {
"api_id": 0, "api_id": 0,
"api_hash": "", "api_hash": "",
@ -30,6 +31,29 @@
"size": 512, "size": 512,
"location": "logs" "location": "logs"
}, },
"features": {
"general": {
"enabled": true
},
"applications": {
"enabled": true
},
"sponsorships": {
"enabled": true
},
"warnings": {
"enabled": true
},
"invites_check": {
"enabled": true
},
"dinovoice": {
"enabled": false
},
"spoilers": {
"enabled": true
}
},
"scheduler": { "scheduler": {
"birthdays": { "birthdays": {
"time": 9, "time": 9,
@ -55,5 +79,135 @@
"locations": { "locations": {
"cache": "cache", "cache": "cache",
"locale": "locale" "locale": "locale"
},
"commands": {
"rules": {
"permissions": [
"users",
"admins"
],
"modules": [
"general"
]
},
"spoiler": {
"permissions": [
"users",
"admins"
],
"modules": [
"spoilers"
]
},
"cancel": {
"permissions": [
"users",
"admins"
],
"modules": [
"spoilers",
"applications",
"sponsorships"
]
},
"nearby": {
"permissions": [
"users",
"admins",
"group_users",
"group_admins"
],
"modules": [
"applications"
]
},
"warn": {
"permissions": [
"group_users"
],
"modules": [
"warnings"
]
},
"reapply": {
"permissions": [
"users",
"admins"
],
"modules": [
"applications"
]
},
"sponsorship": {
"permissions": [
"users",
"admins"
],
"modules": [
"sponsorships"
]
},
"reboot": {
"permissions": [
"owner"
],
"modules": [
"general"
]
},
"label": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"applications"
]
},
"message": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"general"
]
},
"identify": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"applications",
"sponsorships"
]
},
"application": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"applications"
]
},
"applications": {
"permissions": [
"admins",
"group_admins"
],
"modules": [
"applications"
]
},
"resetcommands": {
"permissions": [
"owner"
],
"modules": [
"general"
]
}
} }
} }

View File

@ -19,7 +19,9 @@ from modules.commands.message import *
from modules.commands.nearby import * from modules.commands.nearby import *
from modules.commands.reapply import * from modules.commands.reapply import *
from modules.commands.reboot import * from modules.commands.reboot import *
from modules.commands.resetcommands import *
from modules.commands.rules import * from modules.commands.rules import *
from modules.commands.spoiler import *
from modules.commands.sponsorship import * from modules.commands.sponsorship import *
from modules.commands.start import * from modules.commands.start import *
from modules.commands.warn import * from modules.commands.warn import *
@ -28,6 +30,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.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 *
@ -35,9 +38,9 @@ from modules.callbacks.sus import *
from modules.handlers.confirmation import * from modules.handlers.confirmation import *
from modules.handlers.contact import * from modules.handlers.contact import *
from modules.handlers.group_join import * from modules.handlers.group_join import *
from modules.handlers.sponsorship import *
from modules.handlers.voice import * from modules.handlers.voice import *
from modules.handlers.welcome import * from modules.handlers.welcome import *
from modules.handlers.sponsorship import *
from modules.handlers.everything import * from modules.handlers.everything import *
from modules.scheduled import * from modules.scheduled import *
@ -50,26 +53,6 @@ if __name__ == "__main__":
# I did compare performance, almost no difference and it's much more useful this way. Change my mind. # I did compare performance, almost no difference and it's much more useful this way. Change my mind.
app.start() app.start()
# if configGet("birthdays_notify"):
# every().day.at(configGet("birthdays_time")).do(check_birthdays, app)
# # Background tasks checker
# def background_task():
# try:
# while True:
# try:
# run_pending()
# #print('Checked')
# time.sleep(1)
# except:
# pass
# except KeyboardInterrupt:
# print('\nShutting down')
# killProc(pid)
# t = Thread(target=background_task)
# t.start()
try: try:
app.send_message(configGet("owner"), f"Starting up with pid `{pid}`") app.send_message(configGet("owner"), f"Starting up with pid `{pid}`")
except bad_request_400.PeerIdInvalid: except bad_request_400.PeerIdInvalid:

View File

@ -100,6 +100,15 @@
"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}",
"spoiler_started": "Розпочато створення спойлера. Надішліть щось",
"spoiler_unfinished": "У вас ще є незавершений спойлер. Надішліть /cancel щоб зупинити його створення",
"spoiler_cancel": "Створення спойлера було припинено",
"spoiler_empty": "Спойлер без опису",
"spoiler_described": "Спойлер: {0}",
"spoiler_description_enter": "Добре, введіть бажаний опис спойлера",
"spoiler_using_description": "Встановлено опис спойлера: {0}",
"spoiler_send_description": "Майже впорались. Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.",
"spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.",
"yes": "Так", "yes": "Так",
"no": "Ні", "no": "Ні",
"voice_message": [ "voice_message": [
@ -146,6 +155,17 @@
[ [
"Ні, повторно заповнити" "Ні, повторно заповнити"
] ]
],
"spoiler_description": [
[
"NSFW контент"
],
[
"Деанон холо-учасників"
],
[
"Інше (надішліть свій текст)"
]
] ]
}, },
"force_reply": { "force_reply": {
@ -162,7 +182,9 @@
"sponsor1": "Ім'я дівчини", "sponsor1": "Ім'я дівчини",
"sponsor2": "Дата до якої підписка", "sponsor2": "Дата до якої підписка",
"sponsor3": "Фото-підтвердження", "sponsor3": "Фото-підтвердження",
"sponsor4": "Бажана роль" "sponsor4": "Бажана роль",
"spoiler_content": "Вміст спойлера",
"spoiler_description": "Опис спойлера"
}, },
"button": { "button": {
"sub_yes": "✅ Прийняти", "sub_yes": "✅ Прийняти",
@ -189,7 +211,9 @@
"applying_stop": "🛑 Перервати заповнення", "applying_stop": "🛑 Перервати заповнення",
"done": "✅ Готово", "done": "✅ Готово",
"sponsor_apply": "Заповнити форму", "sponsor_apply": "Заповнити форму",
"sponsor_started": "Форму розпочато" "sponsor_started": "Форму розпочато",
"spoiler_send": "Надіслати",
"spoiler_view": "Переглянути"
}, },
"callback": { "callback": {
"sub_accepted": "✅ Анкету {0} схвалено", "sub_accepted": "✅ Анкету {0} схвалено",
@ -222,6 +246,10 @@
"title": "", "title": "",
"description": "Переглянути анкету {0} (@{1})", "description": "Переглянути анкету {0} (@{1})",
"message_content": "{0} (@{1})\n\n**Дані анкети:**\n{2}" "message_content": "{0} (@{1})\n\n**Дані анкети:**\n{2}"
},
"spoiler": {
"title": "Відправити",
"description": "Надіслати цей спойлер до чату"
} }
}, },
"rules_msg": "📢Правила можуть доповнюватись та змінюватись, залежно від потреби. У такому разі, порушення, які були вчинені до введення (змінення) правила, порушеннями вважатися не будуть. Про всі зміни в правилах, ви будете проінформовані за допомогою закріплених повідомлень. Але вони не будуть закріплені на постійній основі, тому, час від часу, перевіряйте актуальність правил у боті.\n\n🔔Якщо ви бачите, як хтось із учасників порушив правила, тегніть одного із адмінів, у відповідь на повідомлення, яке, на вашу думку, є порушенням. У дописі до тегу, вкажіть, по якому пункту ви побачили порушення. Або перешліть повідомлення до будь кого із адміністраторів у особисті повідомлення, та коротко опишіть ситуацію.\nСписок адміністраторів: @Chirkopol @Za_NerZula @Denialvapr\nЗ питань функціонування бота звертайтесь до @Profitroll2281337\n\n❗Будь-який заборонений контент, може бути відправлений до чату за допомогою бота - https://t.me/spoilerobot з повним описом контенту, що міститься під спойлером. За неправильний або некоректний опис, може бути видане попередження.\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-х попереджень - мут на добу. За повторні порушення, ви одразу отримаєте покарання, без додаткових попереджень.",
@ -238,33 +266,20 @@
], ],
"rules_additional": "Додаткові правила, які несуть рекомендаційний характер, та не мають явних покарань за порушення:\n1⃣) У чаті немає заборони на російську мову. Ми поважаємо кожного українця і не бажаємо розпалювати мовні конфлікти.\n2⃣) У чаті немає заборони на російський контент. Але, майте на увазі, що учасники, здебільшого, не будуть зацікавлені у тому, щоб обговорювати його і він може бути проігнорованим.\n3⃣) Не зловживайте матами. Намагайтесь спілкуватись чистою мовою.\n4⃣) Поважайте авторські права контентмейкерів. Якщо ви знаходите арт, анімацію, музику тощо, на офіційних ресурсах (pixiv, twitter, deviantart тощо), відправляйте на нього посилання.\nЯкщо хтось із учасників відправив арт із не офіційного ресурсу і ви бажаєте дізнатись його автора, відправте у відповідь повідомлення із текстом `/search` на повідомлення із артом.", "rules_additional": "Додаткові правила, які несуть рекомендаційний характер, та не мають явних покарань за порушення:\n1⃣) У чаті немає заборони на російську мову. Ми поважаємо кожного українця і не бажаємо розпалювати мовні конфлікти.\n2⃣) У чаті немає заборони на російський контент. Але, майте на увазі, що учасники, здебільшого, не будуть зацікавлені у тому, щоб обговорювати його і він може бути проігнорованим.\n3⃣) Не зловживайте матами. Намагайтесь спілкуватись чистою мовою.\n4⃣) Поважайте авторські права контентмейкерів. Якщо ви знаходите арт, анімацію, музику тощо, на офіційних ресурсах (pixiv, twitter, deviantart тощо), відправляйте на нього посилання.\nЯкщо хтось із учасників відправив арт із не офіційного ресурсу і ви бажаєте дізнатись його автора, відправте у відповідь повідомлення із текстом `/search` на повідомлення із артом.",
"commands": { "commands": {
"rules": "Правила спільноти", "application": "Переглянути анкету користувача",
"applications": "Отримати всі анкети як JSON",
"cancel": "Відмінити актуальну дію", "cancel": "Відмінити актуальну дію",
"identify": "Дізнатись дані про користувача за айді",
"label": "Встановити нікнейм користувачу",
"message": "Надіслати користувачу повідомлення",
"nearby": "Показати користувачів поблизу", "nearby": "Показати користувачів поблизу",
"reapply": "Повторно заповнити анкету", "reapply": "Повторно заповнити анкету",
"sponsorship": "Отримати роль за спонсорство"
},
"commands_admin": {
"reboot": "Перезапустити бота", "reboot": "Перезапустити бота",
"label": "Встановити нікнейм користувачу", "resetcommands": "Відреєструвати всі команди",
"message": "Надіслати користувачу повідомлення", "rules": "Правила спільноти",
"identify": "Дізнатись дані про користувача за айді", "spoiler": "Почати створювати спойлер",
"warnings": "Переглянути попередження користувача", "sponsorship": "Отримати роль за спонсорство",
"application": "Переглянути анкету користувача",
"applications": "Отримати всі анкети як JSON"
},
"commands_group_admin": {
"reboot": "Перезапустити бота",
"label": "Встановити нікнейм користувачу",
"nearby": "Показати користувачів поблизу",
"message": "Надіслати користувачу повідомлення",
"identify": "Дізнатись дані про користувача за айді",
"warnings": "Переглянути попередження користувача",
"application": "Переглянути анкету користувача",
"applications": "Отримати всі анкети як JSON"
},
"commands_group_destination": {
"warn": "Попередити користувача", "warn": "Попередити користувача",
"nearby": "Показати користувачів поблизу" "warnings": "Переглянути попередження користувача"
} }
} }

View File

@ -16,7 +16,7 @@ async def callback_reapply_query_accept(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
logWrite(f"User {holo_user.id} got their reapplication approved by {clb.from_user.id}") logWrite(f"User {holo_user.id} got their reapplication approved by {clb.from_user.id}")
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))
@ -32,12 +32,12 @@ async def callback_reapply_query_accept(app: Client, clb: CallbackQuery):
need_link = True need_link = True
async for member in app.get_chat_members(configGet("destination_group")): async for member in app.get_chat_members(configGet("users", "groups")):
if member.user.id == holo_user.id: if member.user.id == holo_user.id:
need_link = False need_link = False
if need_link: if need_link:
link = await app.create_chat_invite_link(configGet("destination_group"), name=f"Invite for {holo_user.id}", member_limit=1) #, expire_date=datetime.now()+timedelta(days=1)) link = await app.create_chat_invite_link(configGet("users", "groups"), name=f"Invite for {holo_user.id}", member_limit=1) #, expire_date=datetime.now()+timedelta(days=1))
await app.send_message(holo_user.id, locale("read_rules", "message", locale=holo_user)) await app.send_message(holo_user.id, locale("read_rules", "message", locale=holo_user))
@ -62,7 +62,7 @@ async def callback_query_reapply_reject(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("rejected_by", "message").format(clb.from_user.first_name, fullclb[2]), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("rejected_by", "message").format(clb.from_user.first_name, fullclb[2]), disable_notification=True)
await app.send_message(holo_user.id, locale("rejected", "message", locale=holo_user)) await app.send_message(holo_user.id, locale("rejected", "message", locale=holo_user))
logWrite(f"User {fullclb[2]} got their reapplication rejected by {clb.from_user.id}") logWrite(f"User {fullclb[2]} got their reapplication rejected by {clb.from_user.id}")

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

@ -34,7 +34,7 @@ async def callback_query_sponsor_yes(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("sponsor_approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("sponsor_approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
await app.send_message(holo_user.id, locale("sponsor_approved", "message", locale=holo_user)) await app.send_message(holo_user.id, locale("sponsor_approved", "message", locale=holo_user))
logWrite(f"User {holo_user.id} got sponsorship approved by {clb.from_user.id}") logWrite(f"User {holo_user.id} got sponsorship approved by {clb.from_user.id}")
@ -67,7 +67,7 @@ async def callback_query_sponsor_yes(app: Client, clb: CallbackQuery):
} }
) )
await holo_user.label_set(configGet("destination_group"), col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}})["sponsorship"]["label"]) await holo_user.label_set(configGet("users", "groups"), col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}})["sponsorship"]["label"])
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]] edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
@ -80,7 +80,7 @@ async def callback_query_sponsor_no(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("sponsor_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("sponsor_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
await app.send_message(holo_user.id, locale("sponsor_rejected", "message", locale=holo_user)) await app.send_message(holo_user.id, locale("sponsor_rejected", "message", locale=holo_user))
logWrite(f"User {holo_user.id} got sponsorship rejected by {clb.from_user.id}") logWrite(f"User {holo_user.id} got sponsorship rejected by {clb.from_user.id}")

View File

@ -15,17 +15,17 @@ async def callback_query_accept(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("approved_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
logWrite(f"User {holo_user.id} got approved by {clb.from_user.id}") logWrite(f"User {holo_user.id} got approved by {clb.from_user.id}")
need_link = True need_link = True
async for member in app.get_chat_members(configGet("destination_group")): async for member in app.get_chat_members(configGet("users", "groups")):
if member.user.id == holo_user.id: if member.user.id == holo_user.id:
need_link = False need_link = False
if need_link: if need_link:
link = await app.create_chat_invite_link(configGet("destination_group"), name=f"Invite for {holo_user.id}", member_limit=1) #, expire_date=datetime.now()+timedelta(days=1)) link = await app.create_chat_invite_link(configGet("users", "groups"), name=f"Invite for {holo_user.id}", member_limit=1) #, expire_date=datetime.now()+timedelta(days=1))
await app.send_message(holo_user.id, locale("read_rules", "message", locale=holo_user)) await app.send_message(holo_user.id, locale("read_rules", "message", locale=holo_user))
@ -57,7 +57,7 @@ async def callback_query_reject(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
await app.send_message(holo_user.id, locale("rejected", "message", locale=holo_user)) await app.send_message(holo_user.id, locale("rejected", "message", locale=holo_user))
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id}") logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id}")
@ -74,7 +74,7 @@ async def callback_query_reject_aggressive(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("rejected_by_agr", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) 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)) 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") logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id} due to being aggressive")
@ -91,7 +91,7 @@ async def callback_query_reject_russian(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("rejected_by_rus", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("rejected_by_rus", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
await app.send_message(holo_user.id, locale("rejected_russian", "message", locale=holo_user)) await app.send_message(holo_user.id, locale("rejected_russian", "message", locale=holo_user))
logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id} due to being russian") logWrite(f"User {holo_user.id} got rejected by {clb.from_user.id} due to being russian")

View File

@ -13,7 +13,7 @@ async def callback_query_sus_allow(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("sus_allowed_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("sus_allowed_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
logWrite(f"User {holo_user.id} was allowed to join with another link by {clb.from_user.id}") logWrite(f"User {holo_user.id} was allowed to join with another link by {clb.from_user.id}")
edited_markup = [[InlineKeyboardButton(text=str(locale("sus_allowed", "button")), callback_data="nothing")]] edited_markup = [[InlineKeyboardButton(text=str(locale("sus_allowed", "button")), callback_data="nothing")]]
@ -21,7 +21,7 @@ async def callback_query_sus_allow(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("sus_allowed", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True) await clb.answer(text=locale("sus_allowed", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
await app.restrict_chat_member(configGet("destination_group"), holo_user.id, permissions=ChatPermissions( await app.restrict_chat_member(configGet("users", "groups"), holo_user.id, permissions=ChatPermissions(
can_send_messages=True, can_send_messages=True,
can_send_media_messages=True, can_send_media_messages=True,
can_send_other_messages=True, can_send_other_messages=True,
@ -35,7 +35,7 @@ async def callback_query_sus_reject(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2])) holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("sus_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True) await app.send_message(configGet("admin", "groups"), locale("sus_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
logWrite(f"User {holo_user.id} was rejected to join with another link by {clb.from_user.id}") logWrite(f"User {holo_user.id} was rejected to join with another link by {clb.from_user.id}")
edited_markup = [[InlineKeyboardButton(text=str(locale("sus_rejected", "button")), callback_data="nothing")]] edited_markup = [[InlineKeyboardButton(text=str(locale("sus_rejected", "button")), callback_data="nothing")]]
@ -43,7 +43,7 @@ async def callback_query_sus_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("sus_rejected", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True) await clb.answer(text=locale("sus_rejected", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
await app.ban_chat_member(configGet("destination_group"), holo_user.id) await app.ban_chat_member(configGet("users", "groups"), holo_user.id)
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}}) col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "rejected", "sent": False}})
# ============================================================================================================================== # ==============================================================================================================================

View File

@ -12,7 +12,7 @@ from modules.database import col_applications
from modules import custom_filters from modules import custom_filters
# Applications command ========================================================================================================= # Applications command =========================================================================================================
@app.on_message(~ filters.scheduled & filters.command(["application"], prefixes=["/"]) & custom_filters.admin) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["application"], prefixes=["/"]) & custom_filters.admin)
async def cmd_application(app: Client, msg: Message): async def cmd_application(app: Client, msg: Message):
try: try:
@ -60,7 +60,7 @@ async def cmd_application(app: Client, msg: Message):
# user_id = int(msg.command[1]) # user_id = int(msg.command[1])
# else: # else:
# list_of_users = [] # list_of_users = []
# async for m in app.get_chat_members(configGet("destination_group"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]): # async for m in app.get_chat_members(configGet("users", "groups"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]):
# list_of_users.append(m) # list_of_users.append(m)
# user_id = list_of_users[0].user.id # user_id = list_of_users[0].user.id
# try: # try:

View File

@ -11,7 +11,7 @@ from modules.database import col_applications
from modules import custom_filters from modules import custom_filters
# Applications command ========================================================================================================= # Applications command =========================================================================================================
@app.on_message(~ filters.scheduled & filters.command(["applications"], prefixes=["/"]) & custom_filters.admin) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["applications"], prefixes=["/"]) & custom_filters.admin)
async def cmd_applications(app: Client, msg: Message): async def cmd_applications(app: Client, msg: Message):
logWrite(f"Admin {msg.from_user.id} requested export of a database") logWrite(f"Admin {msg.from_user.id} requested export of a database")

View File

@ -3,10 +3,12 @@ from pyrogram import filters
from pyrogram.types import Message from pyrogram.types import Message
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 from modules.database import col_tmp, col_spoilers
from modules import custom_filters
@app.on_message(~ 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} ) col_tmp.delete_many( {"user": msg.from_user.id} )
col_spoilers.delete_many( {"user": msg.from_user.id, "completed": False} )
await msg.reply_text(locale("cancel", "message", locale=msg.from_user), quote=should_quote(msg)) await msg.reply_text(locale("cancel", "message", locale=msg.from_user), quote=should_quote(msg))
logWrite(f"Cancelling all ongoing tmp operations for {msg.from_user.id}") logWrite(f"Cancelling all ongoing tmp operations for {msg.from_user.id}")

View File

@ -6,10 +6,10 @@ from pyrogram.client import Client
from pyrogram.errors import bad_request_400 from pyrogram.errors import bad_request_400
from pyrogram.enums.chat_action import ChatAction from pyrogram.enums.chat_action import ChatAction
from classes.holo_user import HoloUser, UserNotFoundError, UserInvalidError from classes.holo_user import HoloUser, UserNotFoundError, UserInvalidError
from modules.utils import jsonLoad, should_quote, logWrite, locale, download_tmp, create_tmp from modules.utils import jsonLoad, should_quote, logWrite, locale, download_tmp, create_tmp, find_user
from modules import custom_filters from modules import custom_filters
@app.on_message(~ filters.scheduled & filters.command("identify", prefixes=["/"]) & custom_filters.admin) @app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("identify", prefixes=["/"]) & custom_filters.admin)
async def command_identify(app: Client, msg: Message): async def command_identify(app: Client, msg: Message):
if len(msg.command) != 2: if len(msg.command) != 2:
@ -20,8 +20,8 @@ async def command_identify(app: Client, msg: Message):
try: try:
holo_user = HoloUser(int(msg.command[1])) holo_user = HoloUser(int(msg.command[1]))
except ValueError: except ValueError:
holo_user = HoloUser(await app.get_users(msg.command[1])) holo_user = HoloUser(await find_user(app, msg.command[1]))
except (UserInvalidError, UserNotFoundError, bad_request_400.UsernameInvalid, bad_request_400.PeerIdInvalid, bad_request_400.UsernameNotOccupied): except (UserInvalidError, UserNotFoundError, bad_request_400.UsernameInvalid, bad_request_400.PeerIdInvalid, bad_request_400.UsernameNotOccupied, TypeError):
await msg.reply_text(locale("identify_not_found", "message", locale=msg.from_user).format(msg.command[1])) await msg.reply_text(locale("identify_not_found", "message", locale=msg.from_user).format(msg.command[1]))
return return

View File

@ -6,7 +6,7 @@ from modules.utils import locale, should_quote, find_user
from classes.holo_user import HoloUser, LabelTooLongError from classes.holo_user import HoloUser, LabelTooLongError
from modules import custom_filters from modules import custom_filters
@app.on_message(~ filters.scheduled & filters.command(["label"], prefixes=["/"]) & custom_filters.admin) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["label"], prefixes=["/"]) & custom_filters.admin)
async def cmd_label(app: Client, msg: Message): async def cmd_label(app: Client, msg: Message):
if len(msg.command) < 3: if len(msg.command) < 3:

View File

@ -7,7 +7,7 @@ from modules.utils import logWrite, locale, should_quote
from modules import custom_filters from modules import custom_filters
# Message command ============================================================================================================== # Message command ==============================================================================================================
@app.on_message(~ filters.scheduled & filters.command(["message"], prefixes=["/"]) & custom_filters.admin) @app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.command(["message"], prefixes=["/"]) & custom_filters.admin)
async def cmd_message(app: Client, msg: Message): async def cmd_message(app: Client, msg: Message):
try: try:

View File

@ -11,7 +11,7 @@ from modules.database import col_applications, col_users
from classes.errors.geo import PlaceNotFoundError from classes.errors.geo import PlaceNotFoundError
# Nearby command =============================================================================================================== # Nearby command ===============================================================================================================
@app.on_message(~ filters.scheduled & (filters.private | (filters.chat(configGet("admin_group")) | filters.chat(configGet("destination_group")))) & filters.command(["nearby"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin)) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & (filters.private | (filters.chat(configGet("admin", "groups")) | filters.chat(configGet("users", "groups")))) & filters.command(["nearby"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin))
async def cmd_nearby(app: Client, msg: Message): async def cmd_nearby(app: Client, msg: Message):
holo_user = HoloUser(msg.from_user) holo_user = HoloUser(msg.from_user)

View File

@ -6,9 +6,10 @@ from classes.holo_user import HoloUser
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 from modules.database import col_tmp
from modules import custom_filters
# Reapply command ============================================================================================================== # Reapply command ==============================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["reapply"], prefixes=["/"])) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(["reapply"], prefixes=["/"]))
async def cmd_reapply(app: Client, msg: Message): async def cmd_reapply(app: Client, msg: Message):
holo_user = HoloUser(msg.from_user) holo_user = HoloUser(msg.from_user)
@ -21,7 +22,7 @@ async def cmd_reapply(app: Client, msg: Message):
left_chat = True left_chat = True
async for member in app.get_chat_members(configGet("destination_group")): async for member in app.get_chat_members(configGet("users", "groups")):
if member.user.id == msg.from_user.id: if member.user.id == msg.from_user.id:
left_chat = False left_chat = False

View File

@ -11,7 +11,7 @@ from modules import custom_filters
pid = getpid() pid = getpid()
# Shutdown command ============================================================================================================= # Shutdown command =============================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["/"]) & custom_filters.admin) @app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["/"]) & custom_filters.admin)
async def cmd_kill(app: Client, msg: Message): async def cmd_kill(app: Client, msg: Message):
logWrite(f"Shutting down bot with pid {pid}") logWrite(f"Shutting down bot with pid {pid}")

View File

@ -0,0 +1,65 @@
from app import app
from os import getpid, listdir
from pyrogram import filters
from pyrogram.types import Message, BotCommandScopeDefault, BotCommandScopeChat
from pyrogram.errors import bad_request_400
from pyrogram.client import Client
from modules.utils import logWrite, should_quote, configGet
from modules import custom_filters
pid = getpid()
# Shutdown command =============================================================================================================
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["resetcommands"], prefixes=["/"]) & custom_filters.admin)
async def cmd_kill(app: Client, msg: Message):
if msg.from_user.id == configGet("owner"):
logWrite(f"Resetting all commands on owner's request")
valid_locales = []
files_locales = listdir(f'{configGet("locale", "locations")}')
for entry in files_locales:
if entry.endswith(".json"):
valid_locales.append(".".join(entry.split(".")[:-1]))
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("users", "groups")))
for admin in configGet("admins"):
try:
if configGet("debug") is True:
logWrite(f'Resetting commands for admin {admin}')
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=admin))
except bad_request_400.PeerIdInvalid:
pass
try:
if configGet("debug") is True:
logWrite(f'Resetting commands for owner {configGet("owner")}')
for lc in valid_locales:
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")))
except bad_request_400.PeerIdInvalid:
pass
for lc in valid_locales:
if configGet("debug") is True:
logWrite(f'Resetting commands for locale {lc}')
await app.delete_bot_commands(scope=BotCommandScopeDefault(), language_code=lc)
if configGet("debug") is True:
logWrite(f'Resetting default commands')
await app.delete_bot_commands()
await msg.reply_text("OK", quote=should_quote(msg))
if configGet("debug") is True:
logWrite(str(await app.get_bot_commands()))
logWrite(str(await app.get_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")))))
# ==============================================================================================================================

View File

@ -4,6 +4,7 @@ from pyrogram import filters
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, User, Message from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, User, Message
from pyrogram.client import Client from pyrogram.client import Client
from modules.utils import locale from modules.utils import locale
from modules import custom_filters
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
class DefaultRulesMarkup(list): class DefaultRulesMarkup(list):
@ -35,7 +36,7 @@ class DefaultRulesMarkup(list):
# Rules command ============================================================================================================= # Rules command =============================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["rules"], prefixes=["/"])) @app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["rules"], prefixes=["/"]))
async def cmd_rules(app: Client, msg: Message): async def cmd_rules(app: Client, msg: Message):
await msg.reply_text(locale("rules_msg", locale=msg.from_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(msg.from_user).keyboard) await msg.reply_text(locale("rules_msg", locale=msg.from_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(msg.from_user).keyboard)
# ============================================================================================================================== # ==============================================================================================================================

View File

@ -0,0 +1,41 @@
from app import app
from pyrogram import filters
from pyrogram.types import Message, ForceReply
from pyrogram.client import Client
from classes.holo_user import HoloUser, UserInvalidError, UserNotFoundError
from modules.logging import logWrite
from modules.utils import locale
from modules.database import col_spoilers
from modules import custom_filters
# Spoiler command ==============================================================================================================
@app.on_message(custom_filters.member & ~filters.scheduled & filters.private & filters.command(["spoiler"], prefixes=["/"]))
async def cmd_spoiler(app: Client, msg: Message):
try:
holo_user = HoloUser(msg.from_user)
except (UserInvalidError, UserNotFoundError):
return
if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill":
if col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} ) is None:
col_spoilers.insert_one(
{
"user": msg.from_user.id,
"completed": False,
"description": None,
"photo": None,
"video": None,
"animation": None,
"text": None
}
)
await msg.reply_text(locale("spoiler_started", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_content", "force_reply", locale=msg.from_user)))
logWrite(f"User {msg.from_user.id} started creating new spoiler")
else:
await msg.reply_text(locale("spoiler_unfinished", "message", locale=msg.from_user))
# ==============================================================================================================================

View File

@ -8,7 +8,7 @@ from modules.utils import locale, should_quote
from modules.database import col_applications from modules.database import col_applications
# Sponsorship command ========================================================================================================== # Sponsorship command ==========================================================================================================
@app.on_message(~ filters.scheduled & filters.command(["sponsorship"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin)) @app.on_message(custom_filters.enabled_sponsorships & ~filters.scheduled & filters.command(["sponsorship"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin))
async def cmd_sponsorship(app: Client, msg: Message): async def cmd_sponsorship(app: Client, msg: Message):
if HoloUser(msg.from_user).application_state()[0] == "fill": if HoloUser(msg.from_user).application_state()[0] == "fill":
await msg.reply_text(locale("finish_application", "message", locale=msg.from_user), quote=should_quote(msg)) await msg.reply_text(locale("finish_application", "message", locale=msg.from_user), quote=should_quote(msg))

View File

@ -3,10 +3,13 @@ from pyrogram import filters
from pyrogram.types import ReplyKeyboardMarkup, Message from pyrogram.types import ReplyKeyboardMarkup, Message
from pyrogram.client import Client from pyrogram.client import Client
from modules.utils import locale, logWrite from modules.utils import locale, logWrite
from modules.database import col_users from modules.database import col_users, col_spoilers
from modules import custom_filters
from bson.objectid import ObjectId
from bson.errors import InvalidId
# Start command ================================================================================================================ # Start command ================================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["start"], prefixes=["/"])) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(["start"], prefixes=["/"]))
async def cmd_start(app: Client, msg: Message): async def cmd_start(app: Client, msg: Message):
user = col_users.find_one({"user": msg.from_user.id}) user = col_users.find_one({"user": msg.from_user.id})
@ -25,4 +28,18 @@ async def cmd_start(app: Client, msg: Message):
logWrite(f"User {msg.from_user.id} started bot interaction") logWrite(f"User {msg.from_user.id} started bot interaction")
await msg.reply_text(locale("start", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("welcome", "keyboard", locale=msg.from_user), resize_keyboard=True)) await msg.reply_text(locale("start", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("welcome", "keyboard", locale=msg.from_user), resize_keyboard=True))
if len(msg.command) > 1:
try:
spoiler = col_spoilers.find_one( {"_id": ObjectId(msg.command[1])} )
if spoiler["photo"] is not None:
await msg.reply_photo(spoiler["photo"])
if spoiler["video"] is not None:
await msg.reply_video(spoiler["video"])
if spoiler["animation"] is not None:
await msg.reply_animation(spoiler["animation"])
if spoiler["text"] is not None:
await msg.reply_text(spoiler["text"])
except InvalidId:
await msg.reply_text(f"Got an invalid ID {msg.command[1]}")
# ============================================================================================================================== # ==============================================================================================================================

View File

@ -8,10 +8,10 @@ from modules.database import col_warnings
from modules import custom_filters from modules import custom_filters
# Warn command ================================================================================================================= # Warn command =================================================================================================================
@app.on_message(~ filters.scheduled & filters.command(["warn"], prefixes=["/"]) & custom_filters.admin) @app.on_message(custom_filters.enabled_warnings & ~filters.scheduled & filters.command(["warn"], prefixes=["/"]) & custom_filters.admin)
async def cmd_warn(app: Client, msg: Message): async def cmd_warn(app: Client, msg: Message):
if msg.chat.id == configGet("destination_group"): if msg.chat.id == configGet("users", "groups"):
if msg.reply_to_message_id != None: if msg.reply_to_message_id != None:
message = " ".join(msg.command[1:]) if len(msg.command) > 1 else "" message = " ".join(msg.command[1:]) if len(msg.command) > 1 else ""
col_warnings.insert_one({"user": msg.reply_to_message.from_user.id, "admin": msg.from_user.id, "date": datetime.now(), "reason": message}) col_warnings.insert_one({"user": msg.reply_to_message.from_user.id, "admin": msg.from_user.id, "date": datetime.now(), "reason": message})

View File

@ -8,7 +8,7 @@ from modules.database import col_users, col_warnings
from modules import custom_filters from modules import custom_filters
# Warnings command ============================================================================================================= # Warnings command =============================================================================================================
@app.on_message(~ filters.scheduled & filters.command(["warnings"], prefixes=["/"]) & custom_filters.admin) @app.on_message(custom_filters.enabled_warnings & ~filters.scheduled & filters.command(["warnings"], prefixes=["/"]) & custom_filters.admin)
async def cmd_warnings(app: Client, msg: Message): async def cmd_warnings(app: Client, msg: Message):
if len(msg.command) <= 1: if len(msg.command) <= 1:
@ -21,7 +21,7 @@ async def cmd_warnings(app: Client, msg: Message):
target_name = user_db["tg_name"] target_name = user_db["tg_name"]
except: except:
list_of_users = [] list_of_users = []
async for m in app.get_chat_members(configGet("destination_group"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]): async for m in app.get_chat_members(configGet("users", "groups"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]):
list_of_users.append(m) list_of_users.append(m)
if len(list_of_users) != 0: if len(list_of_users) != 0:

View File

@ -1,16 +1,52 @@
"""Custom message filters made to improve commands """Custom message filters made to improve commands
usage in context of Holo Users.""" usage in context of Holo Users."""
from os import path
from app import isAnAdmin from app import isAnAdmin
from modules.database import col_applications from modules.utils import configGet, jsonLoad
from modules.database import col_applications, col_tmp
from pyrogram import filters from pyrogram import filters
from pyrogram.types import Message from pyrogram.types import Message
async def admin_func(_, __, msg: Message): async def admin_func(_, __, msg: Message):
return await isAnAdmin(msg.from_user.id) return await isAnAdmin(msg.from_user.id)
async def member_func(_, __, msg: Message):
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):
return True if (col_applications.find_one({"user": msg.from_user.id}) is not None) else False return True if (col_applications.find_one({"user": msg.from_user.id}) is not None) else False
async def enabled_general_func(_, __, msg: Message):
return configGet("enabled", "features", "general")
async def enabled_applications_func(_, __, msg: Message):
return configGet("enabled", "features", "applications")
async def enabled_sponsorships_func(_, __, msg: Message):
return configGet("enabled", "features", "sponsorships")
async def enabled_warnings_func(_, __, msg: Message):
return configGet("enabled", "features", "warnings")
async def enabled_invites_check_func(_, __, msg: Message):
return configGet("enabled", "features", "invites_check")
async def enabled_dinovoice_func(_, __, msg: Message):
return configGet("enabled", "features", "dinovoice")
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
admin = filters.create(admin_func) admin = filters.create(admin_func)
member = filters.create(member_func)
allowed = filters.create(allowed_func) allowed = filters.create(allowed_func)
enabled_general = filters.create(enabled_general_func)
enabled_applications = filters.create(enabled_applications_func)
enabled_sponsorships = filters.create(enabled_sponsorships_func)
enabled_warnings = filters.create(enabled_warnings_func)
enabled_invites_check = filters.create(enabled_invites_check_func)
enabled_dinovoice = filters.create(enabled_dinovoice_func)
filling_sponsorship = filters.create(filling_sponsorship_func)

View File

@ -28,13 +28,14 @@ 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", "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_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")
col_applications = db.get_collection("applications") col_applications = db.get_collection("applications")

View File

@ -12,150 +12,157 @@ 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 from modules.database import col_tmp
from modules import custom_filters
# Confirmation ================================================================================================================= # Confirmation =================================================================================================================
confirmation_1 = [] confirmation_1 = []
for pattern in all_locales("confirm", "keyboard"): for pattern in all_locales("confirm", "keyboard"):
confirmation_1.append(pattern[0][0]) confirmation_1.append(pattern[0][0])
@app.on_message(~ filters.scheduled & filters.private & filters.command(confirmation_1, prefixes=[""])) @app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.private & filters.command(confirmation_1, prefixes=[""]))
async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "sponsorship"] = "unknown"): async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "sponsorship", "unknown"] = "unknown"):
holo_user = HoloUser(msg.from_user) holo_user = HoloUser(msg.from_user)
if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)): if configGet("enabled", "features", "applications") is True:
tmp_application = col_tmp.find_one({"user": holo_user.id, "type": "application"}) if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)):
if tmp_application is None: tmp_application = col_tmp.find_one({"user": holo_user.id, "type": "application"})
logWrite(f"Application of {holo_user.id} is nowhere to be found.")
return
if tmp_application["sent"] is True: if tmp_application is None:
return logWrite(f"Application of {holo_user.id} is nowhere to be found.")
return
await msg.reply_text(locale("application_sent", "message"), reply_markup=ReplyKeyboardRemove()) if tmp_application["sent"] is True:
return
application_content = [] await msg.reply_text(locale("application_sent", "message"), reply_markup=ReplyKeyboardRemove())
i = 1
for question in tmp_application['application']: application_content = []
i = 1
if i == 2: for question in tmp_application['application']:
age = relativedelta(datetime.now(), tmp_application['application']['2'])
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)") if i == 2:
elif i == 3: age = relativedelta(datetime.now(), tmp_application['application']['2'])
if tmp_application['application']['3']['countryCode'] == "UA": application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['3']['name']}") elif i == 3:
if tmp_application['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['3']['name']}")
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['3']['name']} ({tmp_application['application']['3']['adminName1']}, {tmp_application['application']['3']['countryName']})")
else: else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application']['3']['name']} ({tmp_application['application']['3']['adminName1']}, {tmp_application['application']['3']['countryName']})") application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application'][question]}")
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application'][question]}")
i += 1 i += 1
if tmp_application["reapply"]: if tmp_application["reapply"]:
await app.send_message(chat_id=configGet("admin_group"), text=(locale("reapply_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup( 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(
[
[ [
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}")
[ ],
InlineKeyboardButton(text=str(locale("reapply_no", "button")), callback_data=f"reapply_no_{holo_user.id}") [
InlineKeyboardButton(text=str(locale("reapply_no", "button")), callback_data=f"reapply_no_{holo_user.id}")
]
] ]
] )
) )
) else:
else: 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(
await app.send_message(chat_id=configGet("admin_group"), text=(locale("application_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup( [
[
InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}")
],
[
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}")
]
]
)
)
logWrite(f"User {holo_user.id} sent his application and it will now be reviewed")
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"sent": True}})
return
# configSet(["sent"], True, file=str(holo_user.id))
# configSet(["confirmed"], True, file=str(holo_user.id))
if configGet("enabled", "features", "sponsorships") is True:
if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)):
tmp_sponsorship = col_tmp.find_one({"user": holo_user.id, "type": "sponsorship"})
if tmp_sponsorship is None:
logWrite(f"Sponsorship of {holo_user.id} is nowhere to be found.")
return
if tmp_sponsorship["sent"] is True:
return
await msg.reply_text(locale("sponsorship_sent", "message"), reply_markup=ReplyKeyboardRemove())
sponsorship_content = []
for question in tmp_sponsorship['sponsorship']:
if question == "expires":
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question].strftime('%d.%m.%Y')}")
elif question == "proof":
filename = uuid1()
with open(f"tmp{sep}{filename}.jpg", "wb") as f:
f.write(tmp_sponsorship['sponsorship']['proof'])
else:
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}")
await app.send_photo(chat_id=configGet("admin", "groups"), photo=f"tmp{sep}{filename}.jpg", caption=(locale("sponsor_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(sponsorship_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
[ [
[ [
InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}") InlineKeyboardButton(text=str(locale("sponsor_yes", "button")), callback_data=f"sponsor_yes_{holo_user.id}")
], ],
[ [
InlineKeyboardButton(text=str(locale("sub_no", "button")), callback_data=f"sub_no_{holo_user.id}") InlineKeyboardButton(text=str(locale("sponsor_no", "button")), callback_data=f"sponsor_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}")
] ]
] ]
) )
) )
logWrite(f"User {holo_user.id} sent his application and it will now be reviewed") remove(f"tmp{sep}{filename}.jpg")
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"sent": True}}) logWrite(f"User {holo_user.id} sent his sponsorship application and it will now be reviewed")
return col_tmp.update_one({"user": holo_user.id, "type": "sponsorship"}, {"$set": {"sent": True}})
# configSet(["sent"], True, file=str(holo_user.id))
# configSet(["confirmed"], True, file=str(holo_user.id))
if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)):
tmp_sponsorship = col_tmp.find_one({"user": holo_user.id, "type": "sponsorship"})
if tmp_sponsorship is None:
logWrite(f"Sponsorship of {holo_user.id} is nowhere to be found.")
return return
if tmp_sponsorship["sent"] is True:
return
await msg.reply_text(locale("sponsorship_sent", "message"), reply_markup=ReplyKeyboardRemove())
sponsorship_content = []
for question in tmp_sponsorship['sponsorship']:
if question == "expires":
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question].strftime('%d.%m.%Y')}")
elif question == "proof":
filename = uuid1()
with open(f"tmp{sep}{filename}.jpg", "wb") as f:
f.write(tmp_sponsorship['sponsorship']['proof'])
else:
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}")
await app.send_photo(chat_id=configGet("admin_group"), photo=f"tmp{sep}{filename}.jpg", caption=(locale("sponsor_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(sponsorship_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(text=str(locale("sponsor_yes", "button")), callback_data=f"sponsor_yes_{holo_user.id}")
],
[
InlineKeyboardButton(text=str(locale("sponsor_no", "button")), callback_data=f"sponsor_no_{holo_user.id}")
]
]
)
)
remove(f"tmp{sep}{filename}.jpg")
logWrite(f"User {holo_user.id} sent his sponsorship application and it will now be reviewed")
col_tmp.update_one({"user": holo_user.id, "type": "sponsorship"}, {"$set": {"sent": True}})
return
confirmation_2 = [] confirmation_2 = []
for pattern in all_locales("confirm", "keyboard"): for pattern in all_locales("confirm", "keyboard"):
confirmation_2.append(pattern[1][0]) confirmation_2.append(pattern[1][0])
@app.on_message(~ filters.scheduled & filters.private & filters.command(confirmation_2, prefixes=[""])) @app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.private & filters.command(confirmation_2, prefixes=[""]))
async def confirm_no(app: Client, msg: Message, kind: Literal["application", "sponsorship"] = "unknown"): async def confirm_no(app: Client, msg: Message, kind: Literal["application", "sponsorship", "unknown"] = "unknown"):
holo_user = HoloUser(msg.from_user) holo_user = HoloUser(msg.from_user)
if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)): if configGet("enabled", "features", "applications") is True:
holo_user.application_restart() if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)):
await welcome_pass(app, msg, once_again=True) holo_user.application_restart()
logWrite(f"User {msg.from_user.id} restarted the application due to typo in it") await welcome_pass(app, msg, once_again=True)
return logWrite(f"User {msg.from_user.id} restarted the application due to typo in it")
return
if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)): if configGet("enabled", "features", "sponsorships") is True:
holo_user.sponsorship_restart() if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)):
await app.send_message(holo_user.id, locale(f"sponsor1", "message", locale=holo_user.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale)))) holo_user.sponsorship_restart()
logWrite(f"User {msg.from_user.id} restarted the sponsorship application due to typo in it") await app.send_message(holo_user.id, locale(f"sponsor1", "message", locale=holo_user.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale))))
return logWrite(f"User {msg.from_user.id} restarted the sponsorship application due to typo in it")
return
# ============================================================================================================================== # ==============================================================================================================================

View File

@ -10,7 +10,7 @@ from classes.holo_user import HoloUser
from modules import custom_filters from modules import custom_filters
# Contact getting ============================================================================================================== # Contact getting ==============================================================================================================
@app.on_message(~ filters.scheduled & filters.contact & filters.private & (custom_filters.allowed | custom_filters.admin)) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.contact & filters.private & (custom_filters.allowed | custom_filters.admin))
async def get_contact(app: Client, msg: Message): async def get_contact(app: Client, msg: Message):
holo_user = HoloUser(msg.from_user) holo_user = HoloUser(msg.from_user)

View File

@ -1,11 +1,11 @@
from app import app, isAnAdmin from app import app, isAnAdmin
import asyncio import asyncio
from pyrogram import filters from pyrogram import filters
from pyrogram.types import Message from pyrogram.types import Message, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton
from pyrogram.client import Client from pyrogram.client import Client
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
from modules.utils import configGet, logWrite from modules.utils import configGet, logWrite, locale, all_locales
from modules.database import col_messages from modules.database import col_messages, col_spoilers
async def message_involved(msg: Message) -> bool: async def message_involved(msg: Message) -> bool:
message = col_messages.find_one({"destination.id": msg.reply_to_message.id, "destination.chat": msg.reply_to_message.chat.id}) message = col_messages.find_one({"destination.id": msg.reply_to_message.id, "destination.chat": msg.reply_to_message.chat.id})
@ -52,8 +52,52 @@ async def any_stage(app: Client, msg: Message):
return return
if msg.text is not None: if msg.text is not None:
await holo_user.application_next(msg.text, msg=msg)
await holo_user.sponsorship_next(msg.text, msg=msg) if configGet("enabled", "features", "applications") is True:
await holo_user.application_next(msg.text, msg=msg)
if configGet("enabled", "features", "sponsorships") is True:
await holo_user.sponsorship_next(msg.text, msg=msg)
if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill":
spoiler = col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} )
if spoiler is None:
return
if msg.photo is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"photo": msg.photo.file_id}} )
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
logWrite(f"Adding photo with id {msg.photo.file_id} to {msg.from_user.id}'s spoiler")
return
if msg.video is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"video": msg.video.file_id}} )
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
logWrite(f"Adding video with id {msg.video.file_id} to {msg.from_user.id}'s spoiler")
return
if msg.animation is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"animation": msg.animation.file_id}} )
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
logWrite(f"Adding animation with id {msg.animation.file_id} to {msg.from_user.id}'s spoiler")
return
if spoiler["photo"] is None and spoiler["video"] is None and spoiler["animation"] is None and spoiler["text"] is None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"text": msg.text}} )
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
logWrite(f"Adding text '{msg.text}' to {msg.from_user.id}'s spoiler")
else:
for lc in all_locales("spoiler_description", "keyboard"):
if msg.text == lc[-1][0]:
await msg.reply_text(locale("spoiler_description_enter", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
return
if msg.text != "-":
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text, "completed": True}} )
logWrite(f"Adding description '{msg.text}' to {msg.from_user.id}'s spoiler")
await msg.reply_text(locale("spoiler_using_description", "message", locale=msg.from_user).format(msg.text), reply_markup=ReplyKeyboardRemove())
await msg.reply_text(locale("spoiler_ready", "message", locale=msg.from_user), quote=False, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_send", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")]]))
# user_stage = configGet("stage", file=str(msg.from_user.id)) # user_stage = configGet("stage", file=str(msg.from_user.id))
@ -116,7 +160,13 @@ async def any_stage(app: Client, msg: Message):
@app.on_message(~ filters.scheduled & filters.group) @app.on_message(~ filters.scheduled & filters.group)
async def message_in_group(app: Client, msg: Message): async def message_in_group(app: Client, msg: Message):
if (msg.chat is not None) and (msg.via_bot is not None): if (msg.chat is not None) and (msg.via_bot is not None):
if (msg.via_bot.id == configGet("bot_id")) and (msg.chat.id == configGet("destination_group")): if (msg.via_bot.id == (await app.get_me()).id) and (msg.chat.id == configGet("users", "groups")):
if msg.text.startswith(locale("spoiler_described", "message").split()[0]) or msg.text.startswith(locale("spoiler_empty", "message").split()[0]):
try:
await msg.forward(configGet("users", "groups"), disable_notification=True)
except:
pass
return
if configGet("remove_application_time") > 0: if configGet("remove_application_time") > 0:
logWrite(f"User {msg.from_user.id} requested application in destination group, removing in {configGet('remove_application_time')} minutes") logWrite(f"User {msg.from_user.id} requested application in destination group, removing in {configGet('remove_application_time')} minutes")
await asyncio.sleep(configGet("remove_application_time")*60) await asyncio.sleep(configGet("remove_application_time")*60)

View File

@ -4,10 +4,11 @@ from pyrogram.client import Client
from modules.utils import configGet, locale from modules.utils import configGet, locale
from modules.logging import logWrite from modules.logging import logWrite
from classes.holo_user import HoloUser from classes.holo_user import HoloUser
from modules import custom_filters
# Filter users on join ========================================================================================================= # Filter users on join =========================================================================================================
@app.on_chat_member_updated(group=configGet("destination_group")) @app.on_chat_member_updated(custom_filters.enabled_invites_check, group=configGet("users", "groups"))
#@app.on_message(filters.new_chat_members, group=configGet("destination_group")) #@app.on_message(filters.new_chat_members, group=configGet("users", "groups"))
async def filter_join(app: Client, member: ChatMemberUpdated): async def filter_join(app: Client, member: ChatMemberUpdated):
if member.invite_link != None: if member.invite_link != None:
@ -24,7 +25,7 @@ async def filter_join(app: Client, member: ChatMemberUpdated):
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}")
await app.send_message(configGet("admin_group"), locale("joined_false_link", "message").format(member.from_user.first_name, member.from_user.id), reply_markup=InlineKeyboardMarkup( await app.send_message(configGet("admin", "groups"), locale("joined_false_link", "message").format(member.from_user.first_name, member.from_user.id), reply_markup=InlineKeyboardMarkup(
[ [
[ [
InlineKeyboardButton(text=str(locale("sus_allow", "button")), callback_data=f"sus_allow_{member.from_user.id}") InlineKeyboardButton(text=str(locale("sus_allow", "button")), callback_data=f"sus_allow_{member.from_user.id}")

View File

@ -2,14 +2,15 @@ from app import app
from pyrogram import filters from pyrogram import filters
from pyrogram.types import Message from pyrogram.types import 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 import custom_filters
@app.on_message(~ filters.scheduled & filters.photo & filters.private) @app.on_message(custom_filters.enabled_sponsorships & custom_filters.filling_sponsorship & ~filters.scheduled & filters.private)
async def sponsor_proof(app: Client, msg: Message): async def sponsor_proof(app: Client, msg: Message):
if msg.via_bot is None: if msg.via_bot is None:
holo_user = HoloUser(msg.from_user) holo_user = HoloUser(msg.from_user)
await holo_user.sponsorship_next(msg.text, msg=msg, photo=msg.photo) if msg.photo is not None:
await holo_user.sponsorship_next(msg.text, msg=msg, photo=msg.photo)

View File

@ -5,8 +5,9 @@ from pyrogram.types import Message
from pyrogram.client import Client from pyrogram.client import Client
from modules.logging import logWrite from modules.logging import logWrite
from modules.utils import configGet, locale from modules.utils import configGet, locale
from modules import custom_filters
@app.on_message(~ filters.scheduled & filters.voice & filters.chat(configGet("destination_group"))) @app.on_message(custom_filters.enabled_dinovoice & ~filters.scheduled & filters.voice & filters.chat(configGet("users", "groups")))
async def voice_message(app: Client, msg: Message): async def voice_message(app: Client, msg: Message):
logWrite(f"User {msg.from_user.id} sent voice message in destination group") logWrite(f"User {msg.from_user.id} sent voice message in destination group")
await msg.reply_text(choice(locale("voice_message", "message"))) await msg.reply_text(choice(locale("voice_message", "message")))

View File

@ -4,6 +4,7 @@ from pyrogram.types import ForceReply, ReplyKeyboardMarkup, 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.utils import all_locales, locale, logWrite from modules.utils import all_locales, locale, logWrite
from modules import custom_filters
# Welcome check ================================================================================================================ # Welcome check ================================================================================================================
welcome_1 = [] welcome_1 = []
@ -11,7 +12,7 @@ for pattern in all_locales("welcome", "keyboard"):
welcome_1.append(pattern[0][0]) welcome_1.append(pattern[0][0])
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(~ 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 = True) -> 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
@ -36,7 +37,7 @@ async def welcome_pass(app: Client, msg: Message, once_again: bool = True) -> No
welcome_2 = [] welcome_2 = []
for pattern in all_locales("welcome", "keyboard"): for pattern in all_locales("welcome", "keyboard"):
welcome_2.append(pattern[1][0]) welcome_2.append(pattern[1][0])
@app.on_message(~ filters.scheduled & filters.private & filters.command(welcome_2, prefixes=[""])) @app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(welcome_2, prefixes=[""]))
async def welcome_reject(app: Client, msg: Message): async def welcome_reject(app: Client, msg: Message):
logWrite(f"User {msg.from_user.id} rejected to start the application") logWrite(f"User {msg.from_user.id} rejected to start the application")

View File

@ -4,18 +4,51 @@ all inline queries that bot receives"""
from datetime import datetime from datetime import datetime
from os import path, sep from os import path, sep
from app import app, isAnAdmin from app import app, isAnAdmin
from pyrogram.types import InlineQueryResultArticle, InputTextMessageContent, InlineQuery from pyrogram.types import InlineQueryResultArticle, InputTextMessageContent, InlineQuery, InlineKeyboardMarkup, InlineKeyboardButton
from pyrogram.client import Client from pyrogram.client import Client
from pyrogram.enums.chat_type import ChatType from pyrogram.enums.chat_type import ChatType
from pyrogram.enums.chat_members_filter import ChatMembersFilter from pyrogram.enums.chat_members_filter import ChatMembersFilter
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from classes.holo_user import HoloUser, UserInvalidError, UserNotFoundError from classes.holo_user import HoloUser, UserInvalidError, UserNotFoundError
from modules.utils import configGet, locale from modules.utils import configGet, locale
from modules.database import col_applications from modules.database import col_applications, col_spoilers
from bson.objectid import ObjectId
from bson.errors import InvalidId
@app.on_inline_query() @app.on_inline_query()
async def inline_answer(client: Client, inline_query: InlineQuery): async def inline_answer(client: Client, inline_query: InlineQuery):
results = []
if inline_query.query.startswith("spoiler:"):
try:
spoil = col_spoilers.find_one( {"_id": ObjectId(inline_query.query.removeprefix("spoiler:"))} )
if spoil is not None:
desc = locale("spoiler_empty", "message", locale=inline_query.from_user) if spoil["description"] is None else locale("spoiler_described", "message", locale=inline_query.from_user).format(spoil["description"])
results = [
InlineQueryResultArticle(
title=locale("title", "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),
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=inline_query.from_user), callback_data=f'sid_{inline_query.query.removeprefix("spoiler:")}')]])
)
]
except InvalidId:
results = []
await inline_query.answer(
results=results
)
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(
results=[ results=[
@ -51,11 +84,9 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
max_results = configGet("inline_preview_count") if inline_query.query != "" else 200 max_results = configGet("inline_preview_count") if inline_query.query != "" else 200
list_of_users = [] list_of_users = []
async for m in app.get_chat_members(configGet("destination_group"), limit=max_results, filter=ChatMembersFilter.SEARCH, query=inline_query.query): async for m in app.get_chat_members(configGet("users", "groups"), limit=max_results, filter=ChatMembersFilter.SEARCH, query=inline_query.query):
list_of_users.append(m) list_of_users.append(m)
results = []
for match in list_of_users: for match in list_of_users:
application = col_applications.find_one({"user": match.user.id}) application = col_applications.find_one({"user": match.user.id})

View File

@ -4,6 +4,7 @@ some scheduled tasks is the main idea of this module"""
from os import listdir, makedirs, path, sep from os import listdir, makedirs, path, sep
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 app import app from app import app
from pyrogram.types import BotCommand, BotCommandScopeChat from pyrogram.types import BotCommand, BotCommandScopeChat
from pyrogram.errors import bad_request_400 from pyrogram.errors import bad_request_400
@ -19,19 +20,19 @@ if configGet("enabled", "scheduler", "cache_members"):
@scheduler.scheduled_job(trigger="interval", seconds=configGet("interval", "scheduler", "cache_members")) @scheduler.scheduled_job(trigger="interval", seconds=configGet("interval", "scheduler", "cache_members"))
async def cache_group_members(): async def cache_group_members():
list_of_users = [] list_of_users = []
async for member in app.get_chat_members(configGet("destination_group")): 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("cache", exist_ok=True) makedirs("cache", exist_ok=True)
jsonSave(list_of_users, f"cache{sep}group_members") jsonSave(list_of_users, path.join(configGet("cache", "locations"), "group_members"))
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"))
async def cache_admins(): async def cache_admins():
list_of_users = [] list_of_users = []
async for member in app.get_chat_members(configGet("admin_group")): 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("cache", exist_ok=True) makedirs("cache", exist_ok=True)
jsonSave(list_of_users, f"cache{sep}admins") jsonSave(list_of_users, path.join(configGet("cache", "locations"), "admins"))
# Cache the avatars of group members # Cache the avatars of group members
if configGet("enabled", "scheduler", "cache_avatars"): if configGet("enabled", "scheduler", "cache_avatars"):
@ -39,124 +40,183 @@ if configGet("enabled", "scheduler", "cache_avatars"):
@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 = []
async for member in app.get_chat_members(configGet("destination_group"), filter=ChatMembersFilter.SEARCH, query=""): async for member in app.get_chat_members(configGet("users", "groups"), filter=ChatMembersFilter.SEARCH, query=""):
list_of_users.append(member.user) list_of_users.append(member.user)
for user in list_of_users: for user in list_of_users:
if user.photo != None: if user.photo != None:
if not path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{user.photo.big_file_id}'): if not path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{user.photo.big_file_id}'):
print(f'Pre-cached avatar {user.photo.big_file_id} of {user.id}', flush=True) print(f'Pre-cached avatar {user.photo.big_file_id} of {user.id}', flush=True)
await app.download_media(user.photo.big_file_id, file_name=f'{configGet("cache", "locations")}{sep}avatars{sep}{user.photo.big_file_id}') await app.download_media(user.photo.big_file_id, file_name=path.join(configGet("cache", "locations"), "avatars", user.photo.big_file_id))
logWrite("Avatars caching performed") logWrite("Avatars caching performed")
# Check for birthdays # Check for birthdays
if configGet("enabled", "scheduler", "birthdays"): if configGet("enabled", "features", "applications") is True:
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "birthdays")) if configGet("enabled", "scheduler", "birthdays") is True:
async def check_birthdays(): @scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "birthdays"))
for entry in col_applications.find(): async def check_birthdays():
if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"): for entry in col_applications.find():
try: if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"):
tg_user = await app.get_users(entry["user"]) try:
await app.send_message( configGet("admin_group"), 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 tg_user = await app.get_users(entry["user"])
logWrite(f"Notified admins about {entry['user']}'s birthday") 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
except Exception as exp: logWrite(f"Notified admins about {entry['user']}'s birthday")
logWrite(f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'") except Exception as exp:
continue logWrite(f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'")
logWrite("Birthdays check performed") continue
logWrite("Birthdays check performed")
# Check for expired sponsorships # Check for expired sponsorships
if configGet("enabled", "scheduler", "sponsorships"): if configGet("enabled", "features", "sponsorships") is True:
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "sponsorships")) if configGet("enabled", "scheduler", "sponsorships") is True:
async def check_sponsors(): @scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "sponsorships"))
for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()+timedelta(days=2)}}): async def check_sponsors():
try: for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()+timedelta(days=2)}}):
tg_user = await app.get_users(entry["user"])
until_expiry = relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days
await app.send_message( tg_user, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore
logWrite(f"Notified user that sponsorship expires in {until_expiry} days")
except Exception as exp:
logWrite(f"Could not find user {entry['user']} notify about sponsorship expiry due to '{exp}'")
continue
for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()}}):
try:
holo_user = HoloUser(entry["user"])
await app.send_message( entry["user"], locale("sponsorships_expired", "message") ) # type: ignore
await holo_user.label_reset(configGet("destination_group"))
col_sponsorships.find_one_and_delete({"user": holo_user.id})
try: try:
tg_user = await app.get_users(entry["user"]) tg_user = await app.get_users(entry["user"])
logWrite(f"Notified user that sponsorship expired") until_expiry = relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days
await app.send_message( tg_user, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore
logWrite(f"Notified user that sponsorship expires in {until_expiry} days")
except Exception as exp: 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 expiry due to '{exp}'")
except Exception as exp: continue
logWrite(f"Could not reset label of user {entry['user']} due to '{exp}'") for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()}}):
continue try:
logWrite("Sponsorships check performed") holo_user = HoloUser(entry["user"])
await app.send_message( entry["user"], locale("sponsorships_expired", "message") ) # type: ignore
await holo_user.label_reset(configGet("users", "groups"))
col_sponsorships.find_one_and_delete({"user": holo_user.id})
try:
tg_user = await app.get_users(entry["user"])
logWrite(f"Notified user that sponsorship expired")
except Exception as exp:
logWrite(f"Could not find user {entry['user']} notify about sponsorship expired due to '{exp}'")
except Exception as exp:
logWrite(f"Could not reset label of user {entry['user']} due to '{exp}'")
continue
logWrite("Sponsorships check performed")
# Register all bot commands # Register all bot commands
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=3)) @scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=3))
async def commands_register(): async def commands_register():
commands = {
"users": [],
"admins": [],
"owner": [],
"group_users": [],
"group_admins": [],
"locales": {}
}
commands_raw = {
"users": [],
"admins": [],
"owner": [],
"group_users": [],
"group_admins": [],
"locales": {}
}
valid_locales = [] valid_locales = []
files_locales = listdir(f'{configGet("locale", "locations")}') files_locales = listdir(f'{configGet("locale", "locations")}')
for entry in files_locales: for entry in files_locales:
if entry.endswith(".json"): if entry.endswith(".json"):
valid_locales.append(".".join(entry.split(".")[:-1])) valid_locales.append(".".join(entry.split(".")[:-1]))
commands["locales"][".".join(entry.split(".")[:-1])] = {
"users": [],
"admins": [],
"owner": [],
"group_users": [],
"group_admins": []
}
if configGet("debug") is True:
commands_raw["locales"][".".join(entry.split(".")[:-1])] = {
"users": [],
"admins": [],
"owner": [],
"group_users": [],
"group_admins": []
}
config_modules = configGet("features")
config_commands = configGet("commands")
for command in config_commands:
enabled = False
for module in config_commands[command]["modules"]:
if config_modules[module]["enabled"] is True:
enabled = True
if enabled is False:
if configGet("debug") is True:
logWrite(f"Not registering {command} at all")
continue
for permission in config_commands[command]["permissions"]:
commands[permission].append(BotCommand(command, locale("commands")[command]))
if configGet("debug") is True:
commands_raw[permission].append({f"{command}": locale("commands")[command]})
logWrite(f"Registering {command} for {permission}")
for lc in valid_locales:
commands["locales"][lc][permission].append(BotCommand(command, locale("commands", locale=lc)[command]))
if configGet("debug") is True:
commands_raw["locales"][lc][permission].append({f"{command}": locale("commands", locale=lc)[command]})
logWrite(f"Registering {command} for {permission} [{lc}]")
# Registering user commands # Registering user commands
commands_list = [] await app.set_bot_commands(commands["users"])
for command in locale("commands"):
commands_list.append(BotCommand(command, locale("commands")[command]))
await app.set_bot_commands(commands_list)
logWrite("Registered user commands for default locale") logWrite("Registered user commands for default locale")
# Registering user commands for each locale # Registering user commands for each locale
for lc in valid_locales: for lc in valid_locales:
commands_list = [] await app.set_bot_commands(commands["locales"][lc]["users"], language_code=lc)
for command in locale("commands", locale=lc):
commands_list.append(BotCommand(command, locale("commands",locale=lc)[command]))
await app.set_bot_commands(commands_list, language_code=lc)
logWrite(f"Registered user commands for locale {lc}") logWrite(f"Registered user commands for locale {lc}")
# Registering admin commands # Registering admin commands
commands_admin_list = []
for command in locale("commands"):
commands_admin_list.append(BotCommand(command, locale("commands")[command]))
for command in locale("commands_admin"):
commands_admin_list.append(BotCommand(command, locale("commands_admin")[command]))
for admin in configGet("admins"): for admin in configGet("admins"):
try: try:
await app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=admin)) await app.set_bot_commands(commands["admins"]+commands["users"], scope=BotCommandScopeChat(chat_id=admin))
logWrite(f"Registered admin commands for admin {admin}") logWrite(f"Registered admin commands for admin {admin}")
except bad_request_400.PeerIdInvalid: except bad_request_400.PeerIdInvalid:
pass pass
# Registering owner commands
try: try:
await app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=configGet("owner"))) await app.set_bot_commands(commands["admins"]+commands["owner"]+commands["users"], scope=BotCommandScopeChat(chat_id=configGet("owner")))
for lc in valid_locales:
await app.set_bot_commands(commands["locales"][lc]["admins"]+commands["locales"][lc]["owner"]+commands["locales"][lc]["users"], scope=BotCommandScopeChat(chat_id=configGet("owner")))
logWrite(f"Registered admin commands for owner {configGet('owner')}") logWrite(f"Registered admin commands for owner {configGet('owner')}")
except bad_request_400.PeerIdInvalid: except bad_request_400.PeerIdInvalid:
logWrite(f"Could not register commands for bot owner. Perhaps user has not started the bot yet.") pass
# Registering admin group commands # Registering admin group commands
commands_group_admin_list = []
for command in locale("commands_group_admin"):
commands_group_admin_list.append(BotCommand(command, locale("commands_group_admin")[command]))
try: try:
await app.set_bot_commands(commands_group_admin_list, scope=BotCommandScopeChat(chat_id=configGet("admin_group"))) await app.set_bot_commands(commands["group_admins"], scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")))
logWrite("Registered admin group commands for default locale") logWrite("Registered admin group commands for default locale")
except bad_request_400.ChannelInvalid: except bad_request_400.ChannelInvalid:
logWrite(f"Could not register commands for admin group. Bot is likely not in the group.") logWrite(f"Could not register commands for admin group. Bot is likely not in the group.")
# Registering destination group commands # Registering destination group commands
commands_group_destination_list = []
for command in locale("commands_group_destination"):
commands_group_destination_list.append(BotCommand(command, locale("commands_group_destination")[command]))
try: try:
await app.set_bot_commands(commands_group_destination_list, scope=BotCommandScopeChat(chat_id=configGet("destination_group"))) await app.set_bot_commands(commands["group_users"], scope=BotCommandScopeChat(chat_id=configGet("users", "groups")))
logWrite("Registered destination group commands") logWrite("Registered destination group commands")
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.")
if configGet("debug") is True:
print(commands, flush=True)
logWrite(f"Complete commands registration:\n{dumps(commands_raw, indent=4, ensure_ascii=False, encode_html_chars=False)}")

43
validation/spoilers.json Normal file
View File

@ -0,0 +1,43 @@
{
"$jsonSchema": {
"required": [
"user",
"completed",
"description",
"photo",
"video",
"animation",
"text"
],
"properties": {
"user": {
"bsonType": ["int", "long"],
"description": "Telegram ID of user"
},
"completed": {
"bsonType": "bool",
"description": "Whether spoiler is a completed one"
},
"description": {
"bsonType": ["string", "null"],
"description": "Spoiler's description"
},
"photo": {
"bsonType": ["string", "null"],
"description": "Spoilered photo"
},
"video": {
"bsonType": ["string", "null"],
"description": "Spoilered video"
},
"animation": {
"bsonType": ["string", "null"],
"description": "Spoilered animation/GIF"
},
"text": {
"bsonType": ["string", "null"],
"description": "Spoilered text"
}
}
}
}