Compare commits

...

4 Commits

Author SHA1 Message Date
Profitroll
3fd56e8b41 Fixed a typo in config keys 2023-01-04 19:59:09 +01:00
Profitroll
3eef04794a Integration of spoilers [WIP] 2023-01-04 19:58:54 +01:00
Profitroll
d59a1671b3 Changed config keys 2023-01-04 19:14:02 +01:00
Profitroll
ccbc135ee4 No need to save bot's ID anymore 2023-01-04 17:26:27 +01:00
28 changed files with 301 additions and 61 deletions

View File

@ -32,15 +32,16 @@ You can see config file with all the comments below:
"locale": "uk",
"debug": false,
"owner": 0,
"bot_id": 0,
"age_allowed": 0,
"api": "http://example.com",
"inline_preview_count": 7,
"admin_group": 0,
"destination_group": 0,
"remove_application_time": -1,
"search_radius": 50,
"admins": [],
"groups": {
"admin": 0,
"users": 0
},
"bot": {
"api_id": 0,
"api_hash": "",
@ -61,6 +62,9 @@ You can see config file with all the comments below:
"location": "logs"
},
"features": {
"general": {
"enabled": true
},
"applications": {
"enabled": true
},

2
app.py
View File

@ -22,7 +22,7 @@ async def isAnAdmin(admin_id):
# Check if user is in admin group
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:
return True
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 dateutil.relativedelta import relativedelta
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.utils import configGet, create_tmp, download_tmp, find_location, locale, should_quote
@ -284,9 +284,9 @@ class HoloUser():
raise LabelTooLongError(label)
self.label = label
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):
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)
except 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.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):
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_pin_messages=False,
can_manage_video_chats=False
@ -544,4 +544,12 @@ class HoloUser():
logWrite(f"User {self.id} completed stage {stage} of sponsorship")
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",
"debug": false,
"owner": 0,
"bot_id": 0,
"age_allowed": 0,
"api": "http://example.com",
"inline_preview_count": 7,
"admin_group": 0,
"destination_group": 0,
"remove_application_time": -1,
"search_radius": 50,
"admins": [],
"groups": {
"admin": 0,
"users": 0
},
"bot": {
"api_id": 0,
"api_hash": "",
@ -86,6 +87,12 @@
"general"
]
},
"spoiler": {
"permissions": [
"users",
"admins"
]
},
"cancel": {
"permissions": [
"users",

View File

@ -20,6 +20,7 @@ from modules.commands.nearby import *
from modules.commands.reapply import *
from modules.commands.reboot import *
from modules.commands.rules import *
from modules.commands.spoiler import *
from modules.commands.sponsorship import *
from modules.commands.start import *
from modules.commands.warn import *
@ -28,6 +29,7 @@ from modules.commands.warnings import *
from modules.callbacks.nothing import *
from modules.callbacks.reapply import *
from modules.callbacks.rules import *
from modules.callbacks.sid import *
from modules.callbacks.sponsorship import *
from modules.callbacks.sub import *
from modules.callbacks.sus import *
@ -35,6 +37,7 @@ from modules.callbacks.sus import *
from modules.handlers.confirmation import *
from modules.handlers.contact import *
from modules.handlers.group_join import *
from modules.handlers.spoiler import *
from modules.handlers.sponsorship import *
from modules.handlers.voice import *
from modules.handlers.welcome import *

View File

@ -100,6 +100,15 @@
"identify_invalid_syntax": "Неправильний синтаксис!\nТреба: `/identify ID/NAME/USERNAME`",
"identify_not_found": "Не знайдено користувачів за запитом **{0}**",
"identify_success": "Користувач `{0}`\n\nІм'я: {1}\nЮзернейм: {2}\nЄ в чаті: {3}\nЄ адміном: {4}\nРоль: {5}\nНаявна анкета: {6}\nНаявне спонсорство: {7}",
"spoiler_started": "Розпочато створення спойлера. Надішліть щось",
"spoiler_unfinished": "У вас ще є незавершений спойлер. Надішліть /cancel щоб зупинити його створення",
"spoiler_cancel": "Створення спойлера було припинено",
"spoiler_empty": "Спойлер без опису",
"spoiler_described": "Спойлер: {0}",
"spoiler_description_enter": "Добре, введіть бажаний опис спойлера",
"spoiler_using_description": "Встановлено опис спойлера: {0}",
"spoiler_send_description": "Майже впорались. Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.",
"spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.",
"yes": "Так",
"no": "Ні",
"voice_message": [
@ -146,6 +155,17 @@
[
"Ні, повторно заповнити"
]
],
"spoiler_description": [
[
"NSFW контент"
],
[
"Деанон холо-учасників"
],
[
"Інше (надішліть свій текст)"
]
]
},
"force_reply": {
@ -162,7 +182,9 @@
"sponsor1": "Ім'я дівчини",
"sponsor2": "Дата до якої підписка",
"sponsor3": "Фото-підтвердження",
"sponsor4": "Бажана роль"
"sponsor4": "Бажана роль",
"spoiler_content": "Вміст спойлера",
"spoiler_description": "Опис спойлера"
},
"button": {
"sub_yes": "✅ Прийняти",
@ -189,7 +211,9 @@
"applying_stop": "🛑 Перервати заповнення",
"done": "✅ Готово",
"sponsor_apply": "Заповнити форму",
"sponsor_started": "Форму розпочато"
"sponsor_started": "Форму розпочато",
"spoiler_send": "Надіслати",
"spoiler_view": "Переглянути"
},
"callback": {
"sub_accepted": "✅ Анкету {0} схвалено",
@ -222,6 +246,10 @@
"title": "",
"description": "Переглянути анкету {0} (@{1})",
"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-х попереджень - мут на добу. За повторні порушення, ви одразу отримаєте покарання, без додаткових попереджень.",
@ -248,6 +276,7 @@
"reapply": "Повторно заповнити анкету",
"reboot": "Перезапустити бота",
"rules": "Правила спільноти",
"spoiler": "Почати створювати спойлер",
"sponsorship": "Отримати роль за спонсорство",
"warn": "Попередити користувача",
"warnings": "Переглянути попередження користувача"

View File

@ -16,7 +16,7 @@ async def callback_reapply_query_accept(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
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}")
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
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:
need_link = False
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))
@ -62,7 +62,7 @@ async def callback_query_reapply_reject(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
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))
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("_")
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))
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")]]
@ -80,7 +80,7 @@ async def callback_query_sponsor_no(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2]))
await app.send_message(configGet("admin_group"), locale("sponsor_rejected_by", "message").format(clb.from_user.first_name, holo_user.id), disable_notification=True)
await app.send_message(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))
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("_")
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}")
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:
need_link = False
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))
@ -57,7 +57,7 @@ async def callback_query_reject(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
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))
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("_")
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))
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("_")
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))
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("_")
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}")
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.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_media_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("_")
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}")
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.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}})
# ==============================================================================================================================

View File

@ -60,7 +60,7 @@ async def cmd_application(app: Client, msg: Message):
# user_id = int(msg.command[1])
# else:
# 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)
# user_id = list_of_users[0].user.id
# try:

View File

@ -3,11 +3,12 @@ from pyrogram import filters
from pyrogram.types import Message
from pyrogram.client import Client
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((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("cancel", prefixes=["/"]))
async def command_cancel(app: Client, msg: Message):
col_tmp.delete_many( {"user": msg.from_user.id} )
col_spoilers.delete_many( {"user": msg.from_user.id, "completed": False} )
await msg.reply_text(locale("cancel", "message", locale=msg.from_user), quote=should_quote(msg))
logWrite(f"Cancelling all ongoing tmp operations for {msg.from_user.id}")

View File

@ -11,7 +11,7 @@ from modules.database import col_applications, col_users
from classes.errors.geo import PlaceNotFoundError
# Nearby command ===============================================================================================================
@app.on_message(custom_filters.enabled_applications & ~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):
holo_user = HoloUser(msg.from_user)

View File

@ -22,7 +22,7 @@ async def cmd_reapply(app: Client, msg: Message):
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:
left_chat = False

View File

@ -0,0 +1,39 @@
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.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)))
else:
await msg.reply_text(locale("spoiler_unfinished", "message", locale=msg.from_user))
# ==============================================================================================================================

View File

@ -3,8 +3,10 @@ from pyrogram import filters
from pyrogram.types import ReplyKeyboardMarkup, Message
from pyrogram.client import Client
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 ================================================================================================================
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(["start"], prefixes=["/"]))
@ -26,4 +28,18 @@ async def cmd_start(app: Client, msg: Message):
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))
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

@ -11,7 +11,7 @@ from modules import custom_filters
@app.on_message(custom_filters.enabled_warnings & ~filters.scheduled & filters.command(["warn"], prefixes=["/"]) & custom_filters.admin)
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:
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})

View File

@ -21,7 +21,7 @@ async def cmd_warnings(app: Client, msg: Message):
target_name = user_db["tg_name"]
except:
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)
if len(list_of_users) != 0:

View File

@ -1,8 +1,9 @@
"""Custom message filters made to improve commands
usage in context of Holo Users."""
from os import path
from app import isAnAdmin
from modules.utils import configGet
from modules.utils import configGet, jsonLoad
from modules.database import col_applications
from pyrogram import filters
from pyrogram.types import Message
@ -10,6 +11,9 @@ from pyrogram.types import Message
async def admin_func(_, __, msg: Message):
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):
return True if (col_applications.find_one({"user": msg.from_user.id}) is not None) else False
@ -32,6 +36,7 @@ async def enabled_dinovoice_func(_, __, msg: Message):
return configGet("enabled", "features", "dinovoice")
admin = filters.create(admin_func)
member = filters.create(member_func)
allowed = filters.create(allowed_func)
enabled_general = filters.create(enabled_general_func)

View File

@ -28,13 +28,14 @@ db = db_client.get_database(name=db_config["name"])
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:
db.create_collection(collection)
col_tmp = db.get_collection("tmp")
col_users = db.get_collection("users")
col_context = db.get_collection("context")
col_spoilers = db.get_collection("spoilers")
col_messages = db.get_collection("messages")
col_warnings = db.get_collection("warnings")
col_applications = db.get_collection("applications")

View File

@ -57,7 +57,7 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
i += 1
if tmp_application["reapply"]:
await app.send_message(chat_id=configGet("admin_group"), text=(locale("reapply_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.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}")
@ -69,7 +69,7 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
)
)
else:
await app.send_message(chat_id=configGet("admin_group"), text=(locale("application_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
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(
[
[
InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}")
@ -124,7 +124,7 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
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(
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("sponsor_yes", "button")), callback_data=f"sponsor_yes_{holo_user.id}")

View File

@ -120,7 +120,7 @@ async def any_stage(app: Client, msg: Message):
@app.on_message(~ filters.scheduled & filters.group)
async def message_in_group(app: Client, msg: Message):
if (msg.chat is not None) and (msg.via_bot is not None):
if (msg.via_bot.id == 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 configGet("remove_application_time") > 0:
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)

View File

@ -7,8 +7,8 @@ from classes.holo_user import HoloUser
from modules import custom_filters
# Filter users on join =========================================================================================================
@app.on_chat_member_updated(custom_filters.enabled_invites_check, group=configGet("destination_group"))
#@app.on_message(filters.new_chat_members, 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("users", "groups"))
async def filter_join(app: Client, member: ChatMemberUpdated):
if member.invite_link != None:
@ -25,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}")
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}")

View File

@ -0,0 +1,86 @@
from app import app
from pyrogram import filters
from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, ForceReply, ReplyKeyboardMarkup, ReplyKeyboardRemove
from pyrogram.client import Client
from classes.holo_user import HoloUser, UserInvalidError, UserNotFoundError
from modules.utils import locale, all_locales
from modules.database import col_spoilers
from modules import custom_filters
# Any other input ==============================================================================================================
@app.on_message(custom_filters.member & ~filters.scheduled & filters.private & filters.text)
async def handler_spoiler_text(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":
spoiler = col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} )
if spoiler is None:
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)))
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}} )
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__()}")]]))
@app.on_message(custom_filters.member & ~filters.scheduled & filters.private & filters.photo)
async def handler_spoiler_photo(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:
return
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)))
@app.on_message(custom_filters.member & ~filters.scheduled & filters.private & filters.video)
async def handler_spoiler_video(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:
return
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)))
@app.on_message(custom_filters.member & ~filters.scheduled & filters.private & filters.animation)
async def handler_spoiler_animation(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:
return
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)))

View File

@ -7,7 +7,7 @@ from modules.logging import logWrite
from modules.utils import configGet, locale
from modules import custom_filters
@app.on_message(custom_filters.enabled_dinovoice & ~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):
logWrite(f"User {msg.from_user.id} sent voice message in destination group")
await msg.reply_text(choice(locale("voice_message", "message")))

View File

@ -4,18 +4,51 @@ all inline queries that bot receives"""
from datetime import datetime
from os import path, sep
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.enums.chat_type import ChatType
from pyrogram.enums.chat_members_filter import ChatMembersFilter
from dateutil.relativedelta import relativedelta
from classes.holo_user import HoloUser, UserInvalidError, UserNotFoundError
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()
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]:
await inline_query.answer(
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
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)
results = []
for match in list_of_users:
application = col_applications.find_one({"user": match.user.id})

View File

@ -19,7 +19,7 @@ if configGet("enabled", "scheduler", "cache_members"):
@scheduler.scheduled_job(trigger="interval", seconds=configGet("interval", "scheduler", "cache_members"))
async def cache_group_members():
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)
makedirs("cache", exist_ok=True)
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "group_members"))
@ -28,7 +28,7 @@ if configGet("enabled", "scheduler", "cache_admins"):
@scheduler.scheduled_job(trigger="interval", seconds=configGet("interval", "scheduler", "cache_admins"))
async def cache_admins():
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)
makedirs("cache", exist_ok=True)
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "admins"))
@ -39,7 +39,7 @@ if configGet("enabled", "scheduler", "cache_avatars"):
@scheduler.scheduled_job(trigger="interval", hours=configGet("interval", "scheduler", "cache_avatars"))
async def cache_avatars():
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)
for user in list_of_users:
if user.photo != None:
@ -58,7 +58,7 @@ if configGet("enabled", "features", "applications") is True:
if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"):
try:
tg_user = await app.get_users(entry["user"])
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
await app.send_message( configGet("admin", "groups"), locale("birthday", "message").format(str(tg_user.first_name), str(tg_user.username), str(relativedelta(datetime.now(), entry["application"]["2"], '%d.%m.%Y').years)) ) # type: ignore
logWrite(f"Notified admins about {entry['user']}'s birthday")
except Exception as exp:
logWrite(f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'")
@ -84,7 +84,7 @@ if configGet("enabled", "features", "sponsorships") is True:
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"))
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"])
@ -165,14 +165,14 @@ async def commands_register():
# Registering admin group commands
try:
await app.set_bot_commands(commands["group_admins"], 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")
except bad_request_400.ChannelInvalid:
logWrite(f"Could not register commands for admin group. Bot is likely not in the group.")
# Registering destination group commands
try:
await app.set_bot_commands(commands["group_users"], 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")
except bad_request_400.ChannelInvalid:
logWrite(f"Could not register commands for destination group. Bot is likely not in the group.")