Data export, warnings' improvements, bug fixes #35

Merged
profitroll merged 30 commits from dev into master 2023-04-02 23:27:31 +03:00
44 changed files with 3243 additions and 936 deletions
Showing only changes of commit 3304339244 - Show all commits

View File

@ -8,21 +8,33 @@ makedirs(f'{configGet("cache", "locations")}{sep}avatars', exist_ok=True)
app = FastAPI(title="HoloUA Avatars API", docs_url=None, redoc_url=None, version="1.0")
@app.get("/check", response_class=JSONResponse, include_in_schema=False)
@app.head("/check", response_class=JSONResponse, include_in_schema=False)
async def check():
return JSONResponse({"detail": "I'm alright, thank you"})
@app.get("/", response_class=FileResponse, include_in_schema=False)
async def avatar_get(avatar_id: str):
if path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}'):
return FileResponse(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}', media_type="image/jpg")
return FileResponse(
f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}',
media_type="image/jpg",
)
else:
raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="File not found")
@app.head("/", response_class=Response, include_in_schema=False)
async def avatar_head(avatar_id: str):
if path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}'):
return Response(headers={"Content-Length": path.getsize(f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}')})
return Response(
headers={
"Content-Length": path.getsize(
f'{configGet("cache", "locations")}{sep}avatars{sep}{avatar_id}'
)
}
)
else:
raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="File not found")

13
app.py
View File

@ -5,10 +5,15 @@ from modules.utils import configGet, jsonLoad
from pyrogram.client import Client
from pyrogram.errors import bad_request_400
app = Client("holochecker", bot_token=configGet("bot_token", "bot"), api_id=configGet("api_id", "bot"), api_hash=configGet("api_hash", "bot"))
app = Client(
"holochecker",
bot_token=configGet("bot_token", "bot"),
api_id=configGet("api_id", "bot"),
api_hash=configGet("api_hash", "bot"),
)
async def isAnAdmin(admin_id):
# Check if user is mentioned in config
if (admin_id == configGet("owner")) or (admin_id in configGet("admins")):
return True
@ -26,7 +31,9 @@ async def isAnAdmin(admin_id):
if member.user.id == admin_id:
return True
except bad_request_400.ChannelInvalid:
logWrite(f"Could not get users in admin group to answer isAnAdmin(). Bot is likely not in the group.")
logWrite(
f"Could not get users in admin group to answer isAnAdmin(). Bot is likely not in the group."
)
return False
return False

View File

@ -1,5 +1,8 @@
class PlaceNotFoundError(Exception):
"""Query provided did not lead to any city or populated area"""
def __init__(self, query):
self.query = query
super().__init__(f"Could not find any place on geonames.org of feature classes A and P by query '{self.query}'")
super().__init__(
f"Could not find any place on geonames.org of feature classes A and P by query '{self.query}'"
)

View File

@ -1,24 +1,38 @@
"""Exceptions that are meant to be used by HoloUser class
and other modules that handle those exceptions"""
class UserNotFoundError(Exception):
"""HoloUser could not find user with such an ID in database"""
def __init__(self, user, user_id):
self.user = user
self.user_id = user_id
super().__init__(f"User of type {type(self.user)} with id {self.user_id} was not found")
super().__init__(
f"User of type {type(self.user)} with id {self.user_id} was not found"
)
class UserInvalidError(Exception):
"""Provided to HoloUser object is not supported"""
def __init__(self, user):
self.user = user
super().__init__(f"Could not find HoloUser by using {type(self.user)} as an input type")
super().__init__(
f"Could not find HoloUser by using {type(self.user)} as an input type"
)
class LabelTooLongError(Exception):
def __init__(self, label: str) -> None:
self.label = label
super().__init__(f"Could not set label to '{label}' because it is {len(label)} characters long (16 is maximum)")
super().__init__(
f"Could not set label to '{label}' because it is {len(label)} characters long (16 is maximum)"
)
class LabelSettingError(Exception):
def __init__(self, exp: Exception, trace: str) -> None:
super().__init__(f"❌ **Could not set label**\n\nException: `{exp}`\n\n**Traceback:**\n```\n{trace}\n```")
super().__init__(
f"❌ **Could not set label**\n\nException: `{exp}`\n\n**Traceback:**\n```\n{trace}\n```"
)

View File

@ -4,17 +4,43 @@ from ftfy import fix_text
from traceback import format_exc
from app import app, isAnAdmin
from typing import Any, List, Literal, Union
from pyrogram.types import User, ChatMember, ChatPrivileges, Chat, Message, Photo, Video, Document, Animation, Voice, ForceReply, ReplyKeyboardMarkup
from pyrogram.types import (
User,
ChatMember,
ChatPrivileges,
Chat,
Message,
Photo,
Video,
Document,
Animation,
Voice,
ForceReply,
ReplyKeyboardMarkup,
)
from pyrogram.errors import bad_request_400
from dateutil.relativedelta import relativedelta
from classes.errors.geo import PlaceNotFoundError
from classes.errors.holo_user import UserInvalidError, UserNotFoundError, LabelTooLongError, LabelSettingError
from classes.errors.holo_user import (
UserInvalidError,
UserNotFoundError,
LabelTooLongError,
LabelSettingError,
)
from classes.templates import DefaultApplicationTemp, DefaultSponsorshipTemp
from modules.database import col_tmp, col_users, col_applications, col_sponsorships, col_messages, col_spoilers
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, find_location, locale, should_quote
class HoloUser():
class HoloUser:
"""This object represents a user of HoloChecker bot.
It is primarily used to interact with a database in a more python-friendly way,
as well as provide better programming experience in case of adding new features, etc.
@ -67,17 +93,32 @@ class HoloUser():
self.username = holo_user["tg_username"]
if isinstance(user, User):
if (self.name != user.first_name) and hasattr(user, "first_name") and (user.first_name is not None):
if (
(self.name != user.first_name)
and hasattr(user, "first_name")
and (user.first_name is not None)
):
self.set("name", user.first_name, db_key="tg_name")
if (self.phone != user.phone_number) and hasattr(user, "phone") and (user.phone_number is not None):
if (
(self.phone != user.phone_number)
and hasattr(user, "phone")
and (user.phone_number is not None)
):
self.set("phone", user.phone_number, db_key="tg_phone")
if (self.locale != user.language_code) and hasattr(user, "locale") and (user.language_code is not None):
if (
(self.locale != user.language_code)
and hasattr(user, "locale")
and (user.language_code is not None)
):
self.set("locale", user.language_code, db_key="tg_locale")
if (self.username != user.username) and hasattr(user, "username") and (user.username is not None):
if (
(self.username != user.username)
and hasattr(user, "username")
and (user.username is not None)
):
self.set("username", user.username, db_key="tg_username")
def set(self, key: str, value: Any, db_key: Union[str, None] = None) -> None:
@ -91,10 +132,13 @@ class HoloUser():
raise AttributeError()
setattr(self, key, value)
db_key = key if db_key is None else db_key
col_users.update_one(filter={"_id": self.db_id}, update={ "$set": { db_key: value } }, upsert=True)
col_users.update_one(
filter={"_id": self.db_id}, update={"$set": {db_key: value}}, upsert=True
)
logWrite(f"Set attribute {key} of user {self.id} to {value}")
async def message(self,
async def message(
self,
context: Message,
origin: Union[Message, None] = None,
text: Union[str, None] = None,
@ -105,7 +149,7 @@ class HoloUser():
animation: Union[str, Animation, None] = None,
voice: Union[str, Voice, None] = None,
adm_origin: bool = False,
adm_context: bool = False
adm_context: bool = False,
) -> None:
"""Send a message to user
@ -130,18 +174,30 @@ class HoloUser():
# Check if any text available and log message sending
if text is not None:
logWrite(f"{context.from_user.id} sent message '{text}' to {self.id} (source message: {context.id})")
logWrite(
f"{context.from_user.id} sent message '{text}' to {self.id} (source message: {context.id})"
)
elif caption is not None:
logWrite(f"{context.from_user.id} sent message '{caption}' to {self.id} (source message: {context.id})")
logWrite(
f"{context.from_user.id} sent message '{caption}' to {self.id} (source message: {context.id})"
)
else:
logWrite(f"{context.from_user.id} sent message to {self.id} (source message: {context.id})")
logWrite(
f"{context.from_user.id} sent message to {self.id} (source message: {context.id})"
)
# Add notices for admin or user
if text is not None:
if adm_context:
text += locale("message_reply_notice", "message")
elif adm_origin:
text = locale("message_from", "message").format(context.from_user.first_name, context.from_user.id) + text + locale("message_reply_notice", "message")
text = (
locale("message_from", "message").format(
context.from_user.first_name, context.from_user.id
)
+ text
+ locale("message_reply_notice", "message")
)
else:
text = locale("message_reply_notice", "message")
@ -149,77 +205,118 @@ class HoloUser():
if adm_context:
caption += locale("message_reply_notice", "message")
elif adm_origin:
caption = locale("message_from", "message").format(context.from_user.first_name, context.from_user.id) + caption + locale("message_reply_notice", "message")
caption = (
locale("message_from", "message").format(
context.from_user.first_name, context.from_user.id
)
+ caption
+ locale("message_reply_notice", "message")
)
else:
caption = locale("message_reply_notice", "message")
# Try sending the message
try:
# Check if origin message exists
# This check decides whether we send_ a message or reply_ to one
if origin is not None:
if photo is not None:
if isinstance(photo, Photo):
photo = photo.file_id
new_message = await origin.reply_cached_media(photo, caption=caption, quote=True)
new_message = await origin.reply_cached_media(
photo, caption=caption, quote=True
)
elif video is not None:
if isinstance(video, Video):
video = video.file_id
new_message = await origin.reply_cached_media(video, caption=caption, quote=True)
new_message = await origin.reply_cached_media(
video, caption=caption, quote=True
)
elif file is not None:
if isinstance(file, Document):
file = file.file_id
new_message = await origin.reply_cached_media(file, caption=caption, quote=True)
new_message = await origin.reply_cached_media(
file, caption=caption, quote=True
)
elif animation is not None:
if isinstance(animation, Animation):
animation = animation.file_id
new_message = await origin.reply_cached_media(animation, caption=caption, quote=True)
new_message = await origin.reply_cached_media(
animation, caption=caption, quote=True
)
elif voice is not None:
if isinstance(voice, Voice):
voice = voice.file_id
new_message = await origin.reply_voice(voice, caption=caption, quote=True)
new_message = await origin.reply_voice(
voice, caption=caption, quote=True
)
else:
new_message = await origin.reply_text(text, quote=True)
else:
if photo is not None:
if isinstance(photo, Photo):
photo = photo.file_id
new_message = await app.send_cached_media(self.id, photo, caption=caption)
new_message = await app.send_cached_media(
self.id, photo, caption=caption
)
elif video is not None:
if isinstance(video, Video):
video = video.file_id
new_message = await app.send_cached_media(self.id, video, caption=caption)
new_message = await app.send_cached_media(
self.id, video, caption=caption
)
elif file is not None:
if isinstance(file, Document):
file = file.file_id
new_message = await app.send_cached_media(self.id, file, caption=caption)
new_message = await app.send_cached_media(
self.id, file, caption=caption
)
elif animation is not None:
if isinstance(animation, Animation):
animation = animation.file_id
new_message = await app.send_cached_media(self.id, animation, caption=caption)
new_message = await app.send_cached_media(
self.id, animation, caption=caption
)
elif voice is not None:
if isinstance(voice, Voice):
voice = voice.file_id
new_message = await app.send_cached_media(self.id, voice, caption=caption)
new_message = await app.send_cached_media(
self.id, voice, caption=caption
)
else:
new_message = await app.send_message(self.id, text)
# Acknowledge sending a message and save entry into DB
await context.reply_text(locale("message_sent", "message"), quote=should_quote(context))
col_messages.insert_one({"origin": {"chat": context.chat.id, "id": context.id}, "destination": {"chat": new_message.chat.id, "id": new_message.id}})
await context.reply_text(
locale("message_sent", "message"), quote=should_quote(context)
)
col_messages.insert_one(
{
"origin": {"chat": context.chat.id, "id": context.id},
"destination": {"chat": new_message.chat.id, "id": new_message.id},
}
)
# Report to admin and to sender about message sending failure
except Exception as exp:
logWrite(f"Exception {exp} happened as {context.from_user.id} tried to send message to {self.id}. Traceback:\n{format_exc()}")
logWrite(
f"Exception {exp} happened as {context.from_user.id} tried to send message to {self.id}. Traceback:\n{format_exc()}"
)
try:
await app.send_message(configGet("owner"), locale("message_traceback", "message").format(context.from_user.id, self.id, exp, format_exc()))
await app.send_message(
configGet("owner"),
locale("message_traceback", "message").format(
context.from_user.id, self.id, exp, format_exc()
),
)
except bad_request_400.PeerIdInvalid:
logWrite(f"Could not notify admin about failure when sending message! Admin has never interacted with bot!")
await context.reply_text(locale("message_error", "message"), quote=should_quote(context))
logWrite(
f"Could not notify admin about failure when sending message! Admin has never interacted with bot!"
)
await context.reply_text(
locale("message_error", "message"), quote=should_quote(context)
)
async def label_set(self, chat: Chat, label: str) -> None:
"""Set label in destination group
@ -232,10 +329,18 @@ class HoloUser():
raise LabelTooLongError(label)
self.label = label
try:
await app.promote_chat_member(configGet("users", "groups"), self.id, privileges=ChatPrivileges(can_pin_messages=True, can_manage_video_chats=True))
await app.promote_chat_member(
configGet("users", "groups"),
self.id,
privileges=ChatPrivileges(
can_pin_messages=True, can_manage_video_chats=True
),
)
if not await isAnAdmin(self.id):
await sleep(0.5)
await app.set_administrator_title(configGet("users", "groups"), self.id, label)
await app.set_administrator_title(
configGet("users", "groups"), self.id, label
)
self.set("label", label)
except Exception as exp:
logWrite(f"Could not set {self.id}'s title to '{self.label}' due to {exp}")
@ -251,13 +356,19 @@ class HoloUser():
self.set("label", "")
await app.set_administrator_title(configGet("users", "groups"), self.id, "")
if not await isAnAdmin(self.id):
await app.promote_chat_member(configGet("users", "groups"), 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
))
can_manage_video_chats=False,
),
)
def application_state(self) -> tuple[Literal["none", "fill", "approved", "rejected"], bool]:
def application_state(
self,
) -> tuple[Literal["none", "fill", "approved", "rejected"], bool]:
"""Check the current state of application in tmp collection
### Returns:
@ -275,15 +386,21 @@ class HoloUser():
### Returns:
* `bool`: `True` if yes and `False` if no
"""
return True if col_applications.find_one({"user": self.id}) is not None else False
return (
True if col_applications.find_one({"user": self.id}) is not None else False
)
def application_restart(self, reapply: bool = False) -> None:
"""Reset application of a user in tmp collection and replace it with an empty one
"""
"""Reset application of a user in tmp collection and replace it with an empty one"""
if col_tmp.find_one({"user": self.id, "type": "application"}) is None:
col_tmp.insert_one(document=DefaultApplicationTemp(self.id, reapply=reapply).dict)
col_tmp.insert_one(
document=DefaultApplicationTemp(self.id, reapply=reapply).dict
)
else:
col_tmp.find_one_and_replace({"user": self.id, "type": "application"}, DefaultApplicationTemp(self.id, reapply=reapply).dict)
col_tmp.find_one_and_replace(
{"user": self.id, "type": "application"},
DefaultApplicationTemp(self.id, reapply=reapply).dict,
)
async def application_next(self, query: str, msg: Message) -> None:
"""Move on filling application of user
@ -317,91 +434,283 @@ class HoloUser():
# return
if progress["state"] == "fill" and progress["sent"] is False:
if msg.text is not None:
msg.text = fix_text(str(msg.text))
if stage == 2:
try:
input_dt = datetime.strptime(query, "%d.%m.%Y")
except ValueError:
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
await msg.reply_text(locale(f"question2_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
logWrite(
f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format"
)
await msg.reply_text(
locale(f"question2_invalid", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"question{stage}",
"force_reply",
locale=self.locale,
)
)
),
)
return
if (datetime.now() <= input_dt) or ((datetime.now() - input_dt).days) > ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_maximum"))).days):
logWrite(f"User {msg.from_user.id} failed stage {stage} due to joking")
await msg.reply_text(locale("question2_joke", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply", locale=self.locale))))
if (datetime.now() <= input_dt) or (
(datetime.now() - input_dt).days
) > (
(
datetime.now()
- datetime.now().replace(
year=datetime.now().year - configGet("age_maximum")
)
).days
):
logWrite(
f"User {msg.from_user.id} failed stage {stage} due to joking"
)
await msg.reply_text(
locale("question2_joke", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale("question2", "force_reply", locale=self.locale)
)
),
)
return
elif ((datetime.now() - input_dt).days) < ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days):
logWrite(f"User {msg.from_user.id} failed stage {stage} due to being underage")
await msg.reply_text(locale("question2_underage", "message", locale=self.locale).format(str(configGet("age_allowed"))), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply", locale=self.locale))))
elif ((datetime.now() - input_dt).days) < (
(
datetime.now()
- datetime.now().replace(
year=datetime.now().year - configGet("age_allowed")
)
).days
):
logWrite(
f"User {msg.from_user.id} failed stage {stage} due to being underage"
)
await msg.reply_text(
locale(
"question2_underage", "message", locale=self.locale
).format(str(configGet("age_allowed"))),
reply_markup=ForceReply(
placeholder=str(
locale("question2", "force_reply", locale=self.locale)
)
),
)
return
else:
progress["application"][str(stage)] = input_dt
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
await msg.reply_text(locale(f"question{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply", locale=self.locale))))
col_tmp.update_one(
{"user": {"$eq": self.id}, "type": {"$eq": "application"}},
{
"$set": {
"application": progress["application"],
"stage": progress["stage"] + 1,
}
},
)
await msg.reply_text(
locale(f"question{stage+1}", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"question{stage+1}",
"force_reply",
locale=self.locale,
)
)
),
)
elif stage == 3:
try:
progress["application"][str(stage)] = find_location(query)
if ("lat" in progress["application"][str(stage)] and "lng" in progress["application"][str(stage)]):
progress["application"][str(stage)]["location"] = [float(progress["application"][str(stage)]["lng"]), float(progress["application"][str(stage)]["lat"])]
if (
"lat" in progress["application"][str(stage)]
and "lng" in progress["application"][str(stage)]
):
progress["application"][str(stage)]["location"] = [
float(progress["application"][str(stage)]["lng"]),
float(progress["application"][str(stage)]["lat"]),
]
del progress["application"][str(stage)]["lat"]
del progress["application"][str(stage)]["lng"]
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
await msg.reply_text(locale("question3_found", "message", locale=self.locale).format(progress["application"][str(stage)]["name"], progress["application"][str(stage)]["adminName1"]))
await msg.reply_text(locale(f"question{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply", locale=self.locale))))
col_tmp.update_one(
{"user": {"$eq": self.id}, "type": {"$eq": "application"}},
{
"$set": {
"application": progress["application"],
"stage": progress["stage"] + 1,
}
},
)
await msg.reply_text(
locale("question3_found", "message", locale=self.locale).format(
progress["application"][str(stage)]["name"],
progress["application"][str(stage)]["adminName1"],
)
)
await msg.reply_text(
locale(f"question{stage+1}", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"question{stage+1}",
"force_reply",
locale=self.locale,
)
)
),
)
except PlaceNotFoundError:
await msg.reply_text(locale("question3_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
await msg.reply_text(
locale("question3_invalid", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"question{stage}",
"force_reply",
locale=self.locale,
)
)
),
)
return
except Exception as exp:
await msg.reply_text(locale("question3_error", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
await msg.reply_text(
locale("question3_error", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"question{stage}",
"force_reply",
locale=self.locale,
)
)
),
)
try:
await app.send_message(configGet("owner"), locale("question3_traceback", "message", locale=self.locale).format(query, exp, format_exc()))
await app.send_message(
configGet("owner"),
locale(
"question3_traceback", "message", locale=self.locale
).format(query, exp, format_exc()),
)
except bad_request_400.PeerIdInvalid:
logWrite(f"Could not notify admin about failure when sending message! Admin has never interacted with bot!")
logWrite(
f"Could not notify admin about failure when sending message! Admin has never interacted with bot!"
)
return
elif stage == 10:
if len(query) > 1024:
await msg.reply_text(locale("question10_too_long", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
await msg.reply_text(
locale("question10_too_long", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"question{stage}",
"force_reply",
locale=self.locale,
)
)
),
)
return
progress["application"][str(stage)] = query
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "complete": True}})
col_tmp.update_one(
{"user": {"$eq": self.id}, "type": {"$eq": "application"}},
{
"$set": {
"application": progress["application"],
"complete": True,
}
},
)
application_content = []
i = 1
for question in progress["application"]:
if i == 2:
age = relativedelta(datetime.now(), progress['application']['2'])
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
age = relativedelta(
datetime.now(), progress["application"]["2"]
)
application_content.append(
f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)"
)
elif i == 3:
if progress['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['3']['name']} ({progress['application']['3']['adminName1']})")
if progress["application"]["3"]["countryCode"] == "UA":
application_content.append(
f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['3']['name']} ({progress['application']['3']['adminName1']})"
)
else:
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['3']['name']} ({progress['application']['3']['adminName1']}, {progress['application']['3']['countryName']})")
application_content.append(
f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application']['3']['name']} ({progress['application']['3']['adminName1']}, {progress['application']['3']['countryName']})"
)
else:
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application'][question]}")
application_content.append(
f"{locale('question'+str(i), 'message', 'question_titles', locale=self.locale)} {progress['application'][question]}"
)
i += 1
await msg.reply_text(locale("confirm", "message", locale=self.locale).format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard", locale=self.locale), resize_keyboard=True))
await msg.reply_text(
locale("confirm", "message", locale=self.locale).format(
"\n".join(application_content)
),
reply_markup=ReplyKeyboardMarkup(
locale("confirm", "keyboard", locale=self.locale),
resize_keyboard=True,
),
)
else:
if len(query) > 256:
await msg.reply_text(locale("question_too_long", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
await msg.reply_text(
locale("question_too_long", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"question{stage}",
"force_reply",
locale=self.locale,
)
)
),
)
return
progress["application"][str(stage)] = query
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
await msg.reply_text(locale(f"question{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage+1}", "force_reply", locale=self.locale))))
col_tmp.update_one(
{"user": {"$eq": self.id}, "type": {"$eq": "application"}},
{
"$set": {
"application": progress["application"],
"stage": progress["stage"] + 1,
}
},
)
await msg.reply_text(
locale(f"question{stage+1}", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"question{stage+1}", "force_reply", locale=self.locale
)
)
),
)
logWrite(f"User {self.id} completed stage {stage} of application")
else:
return
def sponsorship_state(self) -> tuple[Literal["none", "fill", "approved", "rejected"], bool]:
def sponsorship_state(
self,
) -> tuple[Literal["none", "fill", "approved", "rejected"], bool]:
"""Check the current state of sponsorship in tmp collection
### Returns:
@ -419,18 +728,26 @@ class HoloUser():
### Returns:
* `bool`: `True` if yes and `False` if no
"""
return True if col_sponsorships.find_one({"user": self.id, "expires": {"$gt": datetime.now()}}) is not None else False
return (
True
if col_sponsorships.find_one(
{"user": self.id, "expires": {"$gt": datetime.now()}}
)
is not None
else False
)
def sponsorship_restart(self) -> None:
"""Reset sponsorship of a user in tmp collection and replace it with an empty one
"""
"""Reset sponsorship of a user in tmp collection and replace it with an empty one"""
if col_tmp.find_one({"user": self.id, "type": "sponsorship"}) is None:
col_tmp.insert_one(document=DefaultSponsorshipTemp(self.id).dict)
else:
col_tmp.delete_one({"user": self.id, "type": "sponsorship"})
col_tmp.insert_one(document=DefaultSponsorshipTemp(self.id).dict)
async def sponsorship_next(self, query: str, msg: Message, photo: Union[Photo, None] = None) -> None:
async def sponsorship_next(
self, query: str, msg: Message, photo: Union[Photo, None] = None
) -> None:
"""Move on filling sponsorship of user
### Args:
@ -441,7 +758,6 @@ class HoloUser():
progress = col_tmp.find_one({"user": self.id, "type": "sponsorship"})
if progress is not None:
stage = progress["stage"]
if msg.text is not None:
@ -450,58 +766,171 @@ class HoloUser():
msg.caption = fix_text(msg.caption)
if progress["state"] == "fill" and progress["sent"] is False:
if stage == 1:
if len(query) > 240:
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
await msg.reply_text(locale(f"sponsor1_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage}", "force_reply", locale=self.locale))))
logWrite(
f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format"
)
await msg.reply_text(
locale(f"sponsor1_invalid", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"sponsor{stage}",
"force_reply",
locale=self.locale,
)
)
),
)
return
progress["sponsorship"]["streamer"] = query
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}})
await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale))))
col_tmp.update_one(
{"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}},
{
"$set": {
"sponsorship": progress["sponsorship"],
"stage": progress["stage"] + 1,
}
},
)
await msg.reply_text(
locale(f"sponsor{stage+1}", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"sponsor{stage+1}",
"force_reply",
locale=self.locale,
)
)
),
)
elif stage == 2:
try:
input_dt = datetime.strptime(query, "%d.%m.%Y")
except ValueError:
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
await msg.reply_text(locale(f"sponsor2_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage}", "force_reply", locale=self.locale))))
logWrite(
f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format"
)
await msg.reply_text(
locale(f"sponsor2_invalid", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"sponsor{stage}",
"force_reply",
locale=self.locale,
)
)
),
)
return
if datetime.now() >= input_dt:
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending date in the past")
await msg.reply_text(locale("sponsor2_past", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale("sponsor2", "force_reply", locale=self.locale))))
logWrite(
f"User {msg.from_user.id} failed stage {stage} due to sending date in the past"
)
await msg.reply_text(
locale("sponsor2_past", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
"sponsor2", "force_reply", locale=self.locale
)
)
),
)
return
else:
progress["sponsorship"]["expires"] = input_dt
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}})
await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale))))
col_tmp.update_one(
{"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}},
{
"$set": {
"sponsorship": progress["sponsorship"],
"stage": progress["stage"] + 1,
}
},
)
await msg.reply_text(
locale(f"sponsor{stage+1}", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"sponsor{stage+1}",
"force_reply",
locale=self.locale,
)
)
),
)
elif stage == 3:
if photo is not None:
progress["sponsorship"]["proof"] = photo.file_id
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}})
await msg.reply_text(locale(f"sponsor{stage+1}", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage+1}", "force_reply", locale=self.locale))))
col_tmp.update_one(
{"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}},
{
"$set": {
"sponsorship": progress["sponsorship"],
"stage": progress["stage"] + 1,
}
},
)
await msg.reply_text(
locale(f"sponsor{stage+1}", "message", locale=self.locale),
reply_markup=ForceReply(
placeholder=str(
locale(
f"sponsor{stage+1}",
"force_reply",
locale=self.locale,
)
)
),
)
elif stage == 4:
if len(query) > 16:
await msg.reply_text(locale("label_too_long", "message"), reply_markup=ForceReply(placeholder=str(locale("sponsor4", "force_reply", locale=self.locale))))
await msg.reply_text(
locale("label_too_long", "message"),
reply_markup=ForceReply(
placeholder=str(
locale(
"sponsor4", "force_reply", locale=self.locale
)
)
),
)
return
progress["sponsorship"]["label"] = query
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "complete": True}})
col_tmp.update_one(
{"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}},
{
"$set": {
"sponsorship": progress["sponsorship"],
"complete": True,
}
},
)
await msg.reply_cached_media(
progress["sponsorship"]["proof"],
caption=locale("sponsor_confirm", "message", locale=self.locale).format(
caption=locale(
"sponsor_confirm", "message", locale=self.locale
).format(
progress["sponsorship"]["streamer"],
progress["sponsorship"]["expires"].strftime("%d.%m.%Y"),
progress["sponsorship"]["label"]
progress["sponsorship"]["label"],
),
reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard", locale=self.locale), resize_keyboard=True))
reply_markup=ReplyKeyboardMarkup(
locale("confirm", "keyboard", locale=self.locale),
resize_keyboard=True,
),
)
else:
return
@ -517,4 +946,8 @@ class HoloUser():
### 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
return (
False
if col_spoilers.find_one({"user": self.id, "completed": False}) is None
else True
)

View File

@ -2,6 +2,7 @@
from datetime import datetime
class DefaultApplicationTemp(dict):
def __init__(self, user: int, reapply: bool = False):
super().__init__({})
@ -23,10 +24,11 @@ class DefaultApplicationTemp(dict):
"7": None,
"8": None,
"9": None,
"10": None
}
"10": None,
},
}
class DefaultSponsorshipTemp(dict):
def __init__(self, user: int):
super().__init__({})
@ -41,6 +43,6 @@ class DefaultSponsorshipTemp(dict):
"streamer": None,
"expires": datetime.fromtimestamp(0),
"proof": None,
"label": ""
}
"label": "",
},
}

View File

@ -48,7 +48,6 @@ from modules.handlers.everything import *
from modules.scheduled import *
if __name__ == "__main__":
logWrite(f"Starting up with pid {pid}")
# Yes, it should be in some kind of async main() function but I don't give a shit.
@ -57,17 +56,43 @@ if __name__ == "__main__":
try:
if path.exists(path.join(configGet("cache", "locations"), "shutdown_time")):
downtime = relativedelta(datetime.now(), datetime.fromtimestamp(jsonLoad(path.join(configGet("cache", "locations"), "shutdown_time"))["timestamp"]))
downtime = relativedelta(
datetime.now(),
datetime.fromtimestamp(
jsonLoad(
path.join(configGet("cache", "locations"), "shutdown_time")
)["timestamp"]
),
)
if downtime.days >= 1:
app.send_message(configGet("owner"), locale("startup_downtime_days", "message").format(pid, downtime.days))
app.send_message(
configGet("owner"),
locale("startup_downtime_days", "message").format(
pid, downtime.days
),
)
elif downtime.hours >= 1:
app.send_message(configGet("owner"), locale("startup_downtime_hours", "message").format(pid, downtime.hours))
app.send_message(
configGet("owner"),
locale("startup_downtime_hours", "message").format(
pid, downtime.hours
),
)
else:
app.send_message(configGet("owner"), locale("startup_downtime_minutes", "message").format(pid, downtime.minutes))
app.send_message(
configGet("owner"),
locale("startup_downtime_minutes", "message").format(
pid, downtime.minutes
),
)
else:
app.send_message(configGet("owner"), locale("startup", "message").format(pid))
app.send_message(
configGet("owner"), locale("startup", "message").format(pid)
)
except bad_request_400.PeerIdInvalid:
logWrite(f"Could not send startup message to bot owner. Perhaps user has not started the bot yet.")
logWrite(
f"Could not send startup message to bot owner. Perhaps user has not started the bot yet."
)
scheduler.start()
@ -76,11 +101,16 @@ if __name__ == "__main__":
try:
app.send_message(configGet("owner"), locale("shutdown", "message").format(pid))
except bad_request_400.PeerIdInvalid:
logWrite(f"Could not send shutdown message to bot owner. Perhaps user has not started the bot yet.")
logWrite(
f"Could not send shutdown message to bot owner. Perhaps user has not started the bot yet."
)
app.stop()
makedirs(configGet("cache", "locations"), exist_ok=True)
jsonSave({"timestamp": time()}, path.join(configGet("cache", "locations"), "shutdown_time"))
jsonSave(
{"timestamp": time()},
path.join(configGet("cache", "locations"), "shutdown_time"),
)
killProc(pid)

View File

@ -6,17 +6,25 @@ from modules.utils import locale
from modules.database import col_bans
from modules.logging import logWrite
@app.on_callback_query(filters.regex("ban_[\s\S]*"))
async def callback_query_reject(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
if not await isAnAdmin(int(fullclb[1])):
col_bans.insert_one({"user": int(fullclb[1])})
edited_markup = [[InlineKeyboardButton(text=str(locale("banned", "button")), callback_data="nothing")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("banned", "button")), callback_data="nothing"
)
]
]
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.message.edit(
text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup)
)
await clb.answer(text=locale("sub_banned", "callback", locale=clb.from_user))
logWrite(f"User {fullclb[1]} has been banned by {clb.from_user.id}")

View File

@ -4,8 +4,11 @@ from pyrogram.types import CallbackQuery
from pyrogram.client import Client
from modules.utils import locale
# Callback empty ===============================================================================================================
@app.on_callback_query(filters.regex("nothing"))
async def callback_query_nothing(app: Client, clb: CallbackQuery):
await clb.answer(text=locale("nothing", "callback", locale=clb.from_user))
# ==============================================================================================================================

View File

@ -1,6 +1,11 @@
from datetime import datetime
from app import app
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardRemove, CallbackQuery
from pyrogram.types import (
InlineKeyboardMarkup,
InlineKeyboardButton,
ReplyKeyboardRemove,
CallbackQuery,
)
from pyrogram.client import Client
from pyrogram import filters
from classes.holo_user import HoloUser
@ -9,33 +14,85 @@ from modules.handlers.confirmation import confirm_yes
from modules.handlers.welcome import welcome_pass
from modules.database import col_tmp, col_applications
# Callbacks reapply ============================================================================================================
@app.on_callback_query(filters.regex("reapply_yes_[\s\S]*"))
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", "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(
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))
await app.send_message(
holo_user.id, locale("approved_joined", "message", locale=holo_user)
)
applications = col_applications.find({"user": holo_user.id})
if len(list(applications)) > 1:
col_applications.delete_many({"user": holo_user.id})
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
col_applications.insert_one(
{
"user": holo_user.id,
"date": datetime.now(),
"admin": clb.from_user.id,
"application": col_tmp.find_one(
{"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}
)["application"],
}
)
elif applications == 1:
col_applications.find_one_and_replace({"user": holo_user.id}, {"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
col_applications.find_one_and_replace(
{"user": holo_user.id},
{
"user": holo_user.id,
"date": datetime.now(),
"admin": clb.from_user.id,
"application": col_tmp.find_one(
{"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}
)["application"],
},
)
else:
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"state": "approved", "sent": False}})
col_applications.insert_one(
{
"user": holo_user.id,
"date": datetime.now(),
"admin": clb.from_user.id,
"application": col_tmp.find_one(
{"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}
)["application"],
}
)
col_tmp.update_one(
{"user": holo_user.id, "type": "application"},
{"$set": {"state": "approved", "sent": False}},
)
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("accepted", "button")), callback_data="nothing"
)
]
]
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sub_accepted", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
await clb.message.edit(
text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup)
)
await clb.answer(
text=locale("sub_accepted", "callback", locale=clb.from_user).format(
holo_user.id
),
show_alert=True,
)
need_link = True
@ -44,56 +101,107 @@ async def callback_reapply_query_accept(app: Client, clb: CallbackQuery):
need_link = False
if need_link:
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))
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)
)
for rule_msg in locale("rules", locale=holo_user):
await app.send_message(holo_user.id, rule_msg)
await app.send_message(holo_user.id, locale("approved", "message"), reply_markup=InlineKeyboardMarkup(
[[
InlineKeyboardButton(str(locale("join", "button", locale=holo_user)), url=link.invite_link)
]]
))
await app.send_message(
holo_user.id,
locale("approved", "message"),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
str(locale("join", "button", locale=holo_user)),
url=link.invite_link,
)
]
]
),
)
holo_user.set("link", link.invite_link)
logWrite(f"User {holo_user.id} got an invite link {link.invite_link}")
else:
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)
)
@app.on_callback_query(filters.regex("reapply_no_[\s\S]*"))
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", "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}")
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}"
)
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}},
)
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")], [InlineKeyboardButton(text=str(locale("ban", "button")), callback_data=f"ban_{fullclb[2]}")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("declined", "button")), callback_data="nothing"
)
],
[
InlineKeyboardButton(
text=str(locale("ban", "button")), callback_data=f"ban_{fullclb[2]}"
)
],
]
await clb.message.edit(
text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup)
)
await clb.answer(
text=locale("sub_rejected", "callback", locale=clb.from_user).format(
fullclb[2]
),
show_alert=True,
)
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sub_rejected", "callback", locale=clb.from_user).format(fullclb[2]), show_alert=True)
# Use old application when user reapplies after leaving the chat
@app.on_callback_query(filters.regex("reapply_old_[\s\S]*"))
async def callback_query_reapply_old(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
holo_user = HoloUser(clb.from_user)
if holo_user.sponsorship_state()[0] == "fill":
await clb.message.reply_text(locale("finish_sponsorship", "message"), quote=False)
await clb.message.reply_text(
locale("finish_sponsorship", "message"), quote=False
)
return
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
if col_tmp.find_one({"user": holo_user.id, "type": "application"}) is None and col_applications.find_one({"user": holo_user.id}) is not None:
if (
col_tmp.find_one({"user": holo_user.id, "type": "application"}) is None
and col_applications.find_one({"user": holo_user.id}) is not None
):
col_tmp.insert_one(
{
"user": holo_user.id,
@ -103,37 +211,68 @@ async def callback_query_reapply_old(app: Client, clb: CallbackQuery):
"state": "fill",
"reapply": True,
"stage": 10,
"application": col_applications.find_one({"user": holo_user.id})["application"]
"application": col_applications.find_one({"user": holo_user.id})[
"application"
],
}
)
await confirm_yes(app, message, kind="application")
await clb.message.edit(clb.message.text, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("done", "button", locale=clb.from_user), "nothing")]]))
await clb.message.edit(
clb.message.text,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
locale("done", "button", locale=clb.from_user), "nothing"
)
]
]
),
)
# Start a new application when user reapplies after leaving the chat
@app.on_callback_query(filters.regex("reapply_new_[\s\S]*"))
async def callback_query_reapply_new(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
holo_user = HoloUser(clb.from_user)
if holo_user.sponsorship_state()[0] == "fill":
await clb.message.reply_text(locale("finish_sponsorship", "message"), quote=False)
await clb.message.reply_text(
locale("finish_sponsorship", "message"), quote=False
)
return
await clb.answer(locale("reapply_stopped", "callback", locale=clb.from_user))
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
col_tmp.update_one({"user": clb.from_user.id, "type": "application"}, {"$set": {"state": "fill", "completed": False, "stage": 1}})
col_tmp.update_one(
{"user": clb.from_user.id, "type": "application"},
{"$set": {"state": "fill", "completed": False, "stage": 1}},
)
holo_user.application_restart(reapply=True)
await welcome_pass(app, message, once_again=True)
logWrite(f"User {clb.from_user.id} restarted the application after leaving the chat earlier")
await clb.message.edit(clb.message.text, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("done", "button", locale=clb.from_user), "nothing")]]))
logWrite(
f"User {clb.from_user.id} restarted the application after leaving the chat earlier"
)
await clb.message.edit(
clb.message.text,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
locale("done", "button", locale=clb.from_user), "nothing"
)
]
]
),
)
# Abort application fill in progress and restart it
@app.on_callback_query(filters.regex("reapply_stop_[\s\S]*"))
async def callback_query_reapply_stop(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
holo_user = HoloUser(clb.from_user)
@ -142,5 +281,10 @@ async def callback_query_reapply_stop(app: Client, clb: CallbackQuery):
message = await app.get_messages(clb.from_user.id, int(fullclb[2]))
await welcome_pass(app, message, once_again=True)
logWrite(f"User {clb.from_user.id} restarted the application due to typo in it")
await clb.message.edit(locale("reapply_restarted", "message", locale=holo_user), reply_markup=ReplyKeyboardRemove())
await clb.message.edit(
locale("reapply_restarted", "message", locale=holo_user),
reply_markup=ReplyKeyboardRemove(),
)
# ==============================================================================================================================

View File

@ -6,10 +6,10 @@ from pyrogram import filters
from modules.utils import locale, logWrite
from modules.commands.rules import DefaultRulesMarkup
# Callback rule ================================================================================================================
@app.on_callback_query(filters.regex("rule_[\s\S]*"))
async def callback_query_rule(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
logWrite(f"User {clb.from_user.id} requested to check out rule {fullclb[1]}")
@ -18,55 +18,88 @@ async def callback_query_rule(app: Client, clb: CallbackQuery):
if rule_num == len(locale("rules")):
lower_buttons = [
InlineKeyboardButton(locale("rules_prev", "button", locale=clb.from_user), callback_data=f"rule_{rule_num-1}")
InlineKeyboardButton(
locale("rules_prev", "button", locale=clb.from_user),
callback_data=f"rule_{rule_num-1}",
)
]
elif rule_num == 1:
lower_buttons = [
InlineKeyboardButton(locale("rules_next", "button", locale=clb.from_user), callback_data=f"rule_{rule_num+1}")
InlineKeyboardButton(
locale("rules_next", "button", locale=clb.from_user),
callback_data=f"rule_{rule_num+1}",
)
]
else:
lower_buttons = [
InlineKeyboardButton(locale("rules_prev", "button", locale=clb.from_user), callback_data=f"rule_{rule_num-1}"),
InlineKeyboardButton(locale("rules_next", "button", locale=clb.from_user), callback_data=f"rule_{rule_num+1}")
InlineKeyboardButton(
locale("rules_prev", "button", locale=clb.from_user),
callback_data=f"rule_{rule_num-1}",
),
InlineKeyboardButton(
locale("rules_next", "button", locale=clb.from_user),
callback_data=f"rule_{rule_num+1}",
),
]
try:
await clb.message.edit(text=locale("rules", locale=clb.from_user)[rule_num-1], disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup(
await clb.message.edit(
text=locale("rules", locale=clb.from_user)[rule_num - 1],
disable_web_page_preview=True,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("rules_home", "button", locale=clb.from_user), callback_data="rules_home"),
InlineKeyboardButton(locale("rules_additional", "button", locale=clb.from_user), callback_data="rules_additional")
InlineKeyboardButton(
locale("rules_home", "button", locale=clb.from_user),
callback_data="rules_home",
),
InlineKeyboardButton(
locale("rules_additional", "button", locale=clb.from_user),
callback_data="rules_additional",
),
],
lower_buttons
lower_buttons,
]
)
),
)
except bad_request_400.MessageNotModified:
pass
await clb.answer(text=locale("rules_page", "callback", locale=clb.from_user).format(fullclb[1]))
await clb.answer(
text=locale("rules_page", "callback", locale=clb.from_user).format(fullclb[1])
)
@app.on_callback_query(filters.regex("rules_home"))
async def callback_query_rules_home(app: Client, clb: CallbackQuery):
logWrite(f"User {clb.from_user.id} requested to check out homepage rules")
try:
await clb.message.edit(text=locale("rules_msg", locale=clb.from_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(clb.from_user).keyboard)
await clb.message.edit(
text=locale("rules_msg", locale=clb.from_user),
disable_web_page_preview=True,
reply_markup=DefaultRulesMarkup(clb.from_user).keyboard,
)
except bad_request_400.MessageNotModified:
pass
await clb.answer(text=locale("rules_home", "callback", locale=clb.from_user))
@app.on_callback_query(filters.regex("rules_additional"))
async def callback_query_rules_additional(app: Client, clb: CallbackQuery):
logWrite(f"User {clb.from_user.id} requested to check out additional rules")
try:
await clb.message.edit(text=locale("rules_additional", locale=clb.from_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(clb.from_user).keyboard)
await clb.message.edit(
text=locale("rules_additional", locale=clb.from_user),
disable_web_page_preview=True,
reply_markup=DefaultRulesMarkup(clb.from_user).keyboard,
)
except bad_request_400.MessageNotModified:
pass
await clb.answer(text=locale("rules_additional", "callback", locale=clb.from_user))
# ==============================================================================================================================

View File

@ -8,29 +8,78 @@ from bson.objectid import ObjectId
from modules.utils import configGet, jsonLoad, locale
# Callback sid =================================================================================================================
@app.on_callback_query(filters.regex("sid_[\s\S]*"))
async def callback_query_sid(app: Client, clb: CallbackQuery):
await clb.answer(url=f'https://t.me/{(await app.get_me()).username}?start={clb.data.split("_")[1]}')
await clb.answer(
url=f'https://t.me/{(await app.get_me()).username}?start={clb.data.split("_")[1]}'
)
# ==============================================================================================================================
# Callback shc =================================================================================================================
@app.on_callback_query(filters.regex("shc_[\s\S]*"))
async def callback_query_shc(app: Client, clb: CallbackQuery):
if (clb.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))):
await clb.answer(locale("spoiler_forbidden", "callback", locale=clb.from_user), show_alert=True)
if clb.from_user.id not in jsonLoad(
path.join(configGet("cache", "locations"), "group_members")
):
await clb.answer(
locale("spoiler_forbidden", "callback", locale=clb.from_user),
show_alert=True,
)
return
spoil = col_spoilers.find_one({"_id": ObjectId(clb.data.split("_")[1])})
if spoil["description"] == "":
desc = locale("spoiler_empty_named", "message", locale=clb.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), clb.from_user.first_name)
desc = locale("spoiler_empty_named", "message", locale=clb.from_user).format(
locale(spoil["category"], "message", "spoiler_categories"),
clb.from_user.first_name,
)
else:
desc = locale("spoiler_described_named", "message", locale=clb.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), clb.from_user.first_name, spoil["description"])
desc = locale(
"spoiler_described_named", "message", locale=clb.from_user
).format(
locale(spoil["category"], "message", "spoiler_categories"),
clb.from_user.first_name,
spoil["description"],
)
await app.send_message(
configGet("users", "groups"),
desc,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
locale("spoiler_view", "button", locale=clb.from_user),
callback_data=f'sid_{clb.data.split("_")[1]}',
)
]
]
),
)
await app.send_message(
configGet("admin", "groups"),
desc,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
locale("spoiler_view", "button", locale=clb.from_user),
callback_data=f'sid_{clb.data.split("_")[1]}',
)
]
]
),
)
await clb.answer(
locale("spoiler_sent", "callback", locale=clb.from_user), show_alert=True
)
await app.send_message(configGet("users", "groups"), desc, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=clb.from_user), callback_data=f'sid_{clb.data.split("_")[1]}')]]))
await app.send_message(configGet("admin", "groups"), desc, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_view", "button", locale=clb.from_user), callback_data=f'sid_{clb.data.split("_")[1]}')]]))
await clb.answer(locale("spoiler_sent", "callback", locale=clb.from_user), show_alert=True)
# ==============================================================================================================================

View File

@ -1,6 +1,11 @@
from datetime import datetime
from app import app
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ForceReply, CallbackQuery
from pyrogram.types import (
InlineKeyboardMarkup,
InlineKeyboardButton,
ForceReply,
CallbackQuery,
)
from pyrogram.client import Client
from pyrogram import filters
from classes.errors.holo_user import LabelSettingError
@ -8,46 +13,79 @@ from classes.holo_user import HoloUser
from modules.utils import configGet, locale, logWrite, should_quote
from modules.database import col_tmp, col_sponsorships
# Callbacks sponsorship ========================================================================================================
@app.on_callback_query(filters.regex("sponsor_apply_[\s\S]*"))
async def callback_query_sponsor_apply(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
holo_user = HoloUser(int(fullclb[2]))
if holo_user.application_state()[0] == "fill":
await clb.message.reply_text(locale("finish_application", "message"), quote=should_quote(clb.message))
await clb.message.reply_text(
locale("finish_application", "message"), quote=should_quote(clb.message)
)
return
logWrite(f"User {holo_user.id} applied for sponsorship")
holo_user.sponsorship_restart()
edited_markup = [[InlineKeyboardButton(text=str(locale("sponsor_started", "button")), callback_data="nothing")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("sponsor_started", "button")), callback_data="nothing"
)
]
]
await clb.message.edit(
text=locale("sponsorship_applying", "message", locale=holo_user),
reply_markup=InlineKeyboardMarkup(edited_markup),
)
await app.send_message(
holo_user.id,
locale(f"sponsor1", "message", locale=holo_user),
reply_markup=ForceReply(
placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale))
),
)
await clb.answer(
text=locale("sponsor_started", "callback", locale=holo_user).format(
holo_user.id
),
show_alert=False,
)
await clb.message.edit(text=locale("sponsorship_applying", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup(edited_markup))
await app.send_message(holo_user.id, locale(f"sponsor1", "message", locale=holo_user), reply_markup=ForceReply(placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale))))
await clb.answer(text=locale("sponsor_started", "callback", locale=holo_user).format(holo_user.id), show_alert=False)
@app.on_callback_query(filters.regex("sponsor_yes_[\s\S]*"))
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", "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(
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}")
if col_sponsorships.find_one({"user": holo_user.id}) is not None:
col_sponsorships.update_one({"user": holo_user.id},
col_sponsorships.update_one(
{"user": holo_user.id},
{
"$set": {
"date": datetime.now(),
"admin": clb.from_user.id,
"sponsorship": col_tmp.find_one({"user": holo_user.id, "type": "sponsorship"})["sponsorship"]
}
"sponsorship": col_tmp.find_one(
{"user": holo_user.id, "type": "sponsorship"}
)["sponsorship"],
}
},
)
else:
col_sponsorships.insert_one(
@ -55,49 +93,84 @@ async def callback_query_sponsor_yes(app: Client, clb: CallbackQuery):
"user": holo_user.id,
"date": datetime.now(),
"admin": clb.from_user.id,
"sponsorship": col_tmp.find_one({"user": holo_user.id, "type": "sponsorship"})["sponsorship"]
"sponsorship": col_tmp.find_one(
{"user": holo_user.id, "type": "sponsorship"}
)["sponsorship"],
}
)
col_tmp.update_one({"user": holo_user.id, "type":"sponsorship"},
{
"$set": {
"state": "approved",
"sent": False
}
}
col_tmp.update_one(
{"user": holo_user.id, "type": "sponsorship"},
{"$set": {"state": "approved", "sent": False}},
)
try:
await holo_user.label_set(configGet("users", "groups"), 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"],
)
except LabelSettingError as exp:
await app.send_message(configGet("admin", "groups"), exp.__str__(), disable_notification=True)
await app.send_message(
configGet("admin", "groups"), exp.__str__(), disable_notification=True
)
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("accepted", "button")), callback_data="nothing"
)
]
]
await app.edit_message_caption(
clb.message.chat.id,
clb.message.id,
caption=clb.message.caption,
reply_markup=InlineKeyboardMarkup(edited_markup),
)
await clb.answer(
text=locale("sponsor_accepted", "callback").format(fullclb[2]), show_alert=False
)
await app.edit_message_caption(clb.message.chat.id, clb.message.id, caption=clb.message.caption, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sponsor_accepted", "callback").format(fullclb[2]), show_alert=False)
@app.on_callback_query(filters.regex("sponsor_no_[\s\S]*"))
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", "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(
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}")
col_tmp.update_one({"user": holo_user.id, "type": "sponsorship"},
{
"$set": {
"state": "rejected",
"sent": False
}
}
col_tmp.update_one(
{"user": holo_user.id, "type": "sponsorship"},
{"$set": {"state": "rejected", "sent": False}},
)
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("declined", "button")), callback_data="nothing"
)
]
]
await app.edit_message_caption(clb.message.chat.id, clb.message.id, caption=clb.message.caption, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sponsor_rejected", "callback").format(fullclb[2]), show_alert=False)
await app.edit_message_caption(
clb.message.chat.id,
clb.message.id,
caption=clb.message.caption,
reply_markup=InlineKeyboardMarkup(edited_markup),
)
await clb.answer(
text=locale("sponsor_rejected", "callback").format(fullclb[2]), show_alert=False
)

View File

@ -8,14 +8,18 @@ from modules.utils import configGet, locale, logWrite
from modules.database import col_tmp, col_applications
from modules.commands.rules import DefaultRulesMarkup
# Callbacks application ========================================================================================================
@app.on_callback_query(filters.regex("sub_yes_[\s\S]*"))
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", "groups"), 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
@ -25,63 +29,165 @@ async def callback_query_accept(app: Client, clb: CallbackQuery):
need_link = False
if need_link:
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))
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)
)
await app.send_message(holo_user.id, locale("rules_msg", locale=holo_user), disable_web_page_preview=True, reply_markup=DefaultRulesMarkup(holo_user).keyboard)
await app.send_message(
holo_user.id,
locale("rules_msg", locale=holo_user),
disable_web_page_preview=True,
reply_markup=DefaultRulesMarkup(holo_user).keyboard,
)
await app.send_message(holo_user.id, locale("approved", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup(
[[
InlineKeyboardButton(str(locale("join", "button", locale=holo_user)), url=link.invite_link)
]]
))
await app.send_message(
holo_user.id,
locale("approved", "message", locale=holo_user),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
str(locale("join", "button", locale=holo_user)),
url=link.invite_link,
)
]
]
),
)
holo_user.set("link", link.invite_link)
logWrite(f"User {holo_user.id} got an invite link {link.invite_link}")
else:
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)
)
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
col_tmp.update_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}, {"$set": {"state": "approved", "sent": False}})
col_applications.insert_one(
{
"user": holo_user.id,
"date": datetime.now(),
"admin": clb.from_user.id,
"application": col_tmp.find_one(
{"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}}
)["application"],
}
)
col_tmp.update_one(
{"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}},
{"$set": {"state": "approved", "sent": False}},
)
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("accepted", "button")), callback_data="nothing"
)
]
]
await clb.message.edit(
text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup)
)
await clb.answer(
text=locale("sub_accepted", "callback", locale=clb.from_user).format(
holo_user.id
),
show_alert=True,
)
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sub_accepted", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
@app.on_callback_query(filters.regex("sub_no_[\s\S]*"))
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", "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(
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}")
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}},
)
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")], [InlineKeyboardButton(text=str(locale("ban", "button")), callback_data=f"ban_{fullclb[2]}")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("declined", "button")), callback_data="nothing"
)
],
[
InlineKeyboardButton(
text=str(locale("ban", "button")), callback_data=f"ban_{fullclb[2]}"
)
],
]
await clb.message.edit(
text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup)
)
await clb.answer(
text=locale("sub_rejected", "callback", locale=clb.from_user).format(
holo_user.id
),
show_alert=True,
)
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sub_rejected", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
@app.on_callback_query(filters.regex("sub_russian_[\s\S]*"))
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", "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")
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"
)
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}},
)
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("declined", "button")), callback_data="nothing"
)
]
]
await clb.message.edit(
text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup)
)
await clb.answer(
text=locale("sub_russian", "callback", locale=clb.from_user).format(
holo_user.id
),
show_alert=True,
)
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button")), callback_data="nothing")]]
await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
await clb.answer(text=locale("sub_russian", "callback", locale=clb.from_user).format(holo_user.id), show_alert=True)
# ==============================================================================================================================

View File

@ -1,49 +1,104 @@
from app import app
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ChatPermissions, CallbackQuery
from pyrogram.types import (
InlineKeyboardMarkup,
InlineKeyboardButton,
ChatPermissions,
CallbackQuery,
)
from pyrogram.client import Client
from pyrogram import filters
from classes.holo_user import HoloUser
from modules.utils import configGet, locale, logWrite
from modules.database import col_tmp
# Callbacks sus users ==========================================================================================================
@app.on_callback_query(filters.regex("sus_allow_[\s\S]*"))
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", "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}")
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")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("sus_allowed", "button")), callback_data="nothing"
)
]
]
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.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("users", "groups"), 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,
can_send_polls=True
)
can_send_polls=True,
),
)
@app.on_callback_query(filters.regex("sus_reject_[\s\S]*"))
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", "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}")
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")]]
edited_markup = [
[
InlineKeyboardButton(
text=str(locale("sus_rejected", "button")), callback_data="nothing"
)
]
]
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.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("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,51 +12,92 @@ from dateutil.relativedelta import relativedelta
from modules.database import col_applications
from modules import custom_filters
# Application command ==========================================================================================================
@app.on_message(custom_filters.enabled_applications & ~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):
try:
try:
holo_user = HoloUser(int(msg.command[1]))
except (ValueError, UserNotFoundError):
try:
holo_user = HoloUser((await app.get_users(msg.command[1])).id)
except (bad_request_400.UsernameInvalid, bad_request_400.PeerIdInvalid, bad_request_400.UsernameNotOccupied):
await msg.reply_text(locale("no_user_application", "message", locale=msg.from_user).format(msg.command[1]), quote=should_quote(msg))
except (
bad_request_400.UsernameInvalid,
bad_request_400.PeerIdInvalid,
bad_request_400.UsernameNotOccupied,
):
await msg.reply_text(
locale(
"no_user_application", "message", locale=msg.from_user
).format(msg.command[1]),
quote=should_quote(msg),
)
return
application = col_applications.find_one({"user": holo_user.id})
if application is None:
logWrite(f"User {msg.from_user.id} requested application of {holo_user.id} but user does not exists")
await msg.reply_text(locale("user_invalid", "message", locale=msg.from_user), quote=should_quote(msg))
logWrite(
f"User {msg.from_user.id} requested application of {holo_user.id} but user does not exists"
)
await msg.reply_text(
locale("user_invalid", "message", locale=msg.from_user),
quote=should_quote(msg),
)
return
application_content = []
i = 1
for question in application['application']:
for question in application["application"]:
if i == 2:
age = relativedelta(datetime.now(), application['application']['2'])
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
age = relativedelta(datetime.now(), application["application"]["2"])
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)"
)
elif i == 3:
if application['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['3']['name']}")
if application["application"]["3"]["countryCode"] == "UA":
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['3']['name']}"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application'][question]}")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=msg.from_user)} {application['application'][question]}"
)
i += 1
application_status = locale("application_status_accepted", "message", locale=msg.from_user).format((await app.get_users(application["admin"])).first_name, application["date"].strftime("%d.%m.%Y, %H:%M"))
application_status = locale(
"application_status_accepted", "message", locale=msg.from_user
).format(
(await app.get_users(application["admin"])).first_name,
application["date"].strftime("%d.%m.%Y, %H:%M"),
)
logWrite(f"User {msg.from_user.id} requested application of {holo_user.id}")
await msg.reply_text(locale("contact", "message", locale=msg.from_user).format(holo_user.id, "\n".join(application_content), application_status), parse_mode=ParseMode.MARKDOWN, quote=should_quote(msg))
await msg.reply_text(
locale("contact", "message", locale=msg.from_user).format(
holo_user.id, "\n".join(application_content), application_status
),
parse_mode=ParseMode.MARKDOWN,
quote=should_quote(msg),
)
except IndexError:
await msg.reply_text(locale("application_invalid_syntax", "message", locale=msg.from_user), quote=should_quote(msg))
await msg.reply_text(
locale("application_invalid_syntax", "message", locale=msg.from_user),
quote=should_quote(msg),
)
# ==============================================================================================================================

View File

@ -10,10 +10,15 @@ from modules.utils import should_quote, jsonSave
from modules.database import col_applications
from modules import custom_filters
# Applications command =========================================================================================================
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["applications"], prefixes=["/"]) & custom_filters.admin)
async def cmd_applications(app: Client, msg: Message):
# Applications command =========================================================================================================
@app.on_message(
custom_filters.enabled_applications
& ~filters.scheduled
& filters.command(["applications"], prefixes=["/"])
& custom_filters.admin
)
async def cmd_applications(app: Client, msg: Message):
logWrite(f"Admin {msg.from_user.id} requested export of a database")
await app.send_chat_action(msg.chat.id, ChatAction.UPLOAD_DOCUMENT)
filename = uuid1()
@ -21,10 +26,18 @@ async def cmd_applications(app: Client, msg: Message):
for entry in col_applications.find():
del entry["_id"]
entry["date"] = entry["date"].strftime("%d.%m.%Y, %H:%M")
entry["application"]["2"] = entry["application"]["2"].strftime("%d.%m.%Y, %H:%M")
entry["application"]["2"] = entry["application"]["2"].strftime(
"%d.%m.%Y, %H:%M"
)
output.append(entry)
makedirs("tmp", exist_ok=True)
jsonSave(output, f"tmp{sep}{filename}.json")
await msg.reply_document(document=f"tmp{sep}{filename}.json", file_name="applications", quote=should_quote(msg))
await msg.reply_document(
document=f"tmp{sep}{filename}.json",
file_name="applications",
quote=should_quote(msg),
)
remove(f"tmp{sep}{filename}.json")
# ==============================================================================================================================

View File

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

View File

@ -7,15 +7,30 @@ from pyrogram.errors import bad_request_400
from pyrogram.enums.chat_action import ChatAction
from classes.errors.holo_user import UserNotFoundError, UserInvalidError
from classes.holo_user import HoloUser
from modules.utils import jsonLoad, should_quote, logWrite, locale, download_tmp, create_tmp, find_user
from modules.utils import (
jsonLoad,
should_quote,
logWrite,
locale,
download_tmp,
create_tmp,
find_user,
)
from modules import custom_filters
# Identify command =============================================================================================================
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("identify", prefixes=["/"]) & custom_filters.admin)
async def cmd_identify(app: Client, msg: Message):
# Identify command =============================================================================================================
@app.on_message(
(custom_filters.enabled_applications | custom_filters.enabled_sponsorships)
& ~filters.scheduled
& filters.command("identify", prefixes=["/"])
& custom_filters.admin
)
async def cmd_identify(app: Client, msg: Message):
if len(msg.command) != 2:
await msg.reply_text(locale("identify_invalid_syntax", "message", locale=msg.from_user))
await msg.reply_text(
locale("identify_invalid_syntax", "message", locale=msg.from_user)
)
return
try:
@ -23,17 +38,44 @@ async def cmd_identify(app: Client, msg: Message):
holo_user = HoloUser(int(msg.command[1]))
except ValueError:
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, TypeError):
await msg.reply_text(locale("identify_not_found", "message", locale=msg.from_user).format(msg.command[1]))
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]
)
)
return
role = holo_user.label
has_application = locale("yes", "message", locale=msg.from_user) if holo_user.application_approved() is True else locale("no", "message", locale=msg.from_user)
has_sponsorship = locale("yes", "message", locale=msg.from_user) if holo_user.sponsorship_valid() is True else locale("no", "message", locale=msg.from_user)
has_application = (
locale("yes", "message", locale=msg.from_user)
if holo_user.application_approved() is True
else locale("no", "message", locale=msg.from_user)
)
has_sponsorship = (
locale("yes", "message", locale=msg.from_user)
if holo_user.sponsorship_valid() is True
else locale("no", "message", locale=msg.from_user)
)
username = holo_user.username if holo_user.username is not None else "N/A"
in_chat = locale("yes", "message", locale=msg.from_user) if (holo_user.id in jsonLoad(path.join("cache", "group_members"))) else locale("no", "message", locale=msg.from_user)
is_admin = locale("yes", "message", locale=msg.from_user) if (await isAnAdmin(holo_user.id)) else locale("no", "message", locale=msg.from_user)
in_chat = (
locale("yes", "message", locale=msg.from_user)
if (holo_user.id in jsonLoad(path.join("cache", "group_members")))
else locale("no", "message", locale=msg.from_user)
)
is_admin = (
locale("yes", "message", locale=msg.from_user)
if (await isAnAdmin(holo_user.id))
else locale("no", "message", locale=msg.from_user)
)
output = locale("identify_success", "message", locale=msg.from_user).format(
holo_user.id,
@ -43,7 +85,7 @@ async def cmd_identify(app: Client, msg: Message):
is_admin,
role,
has_application,
has_sponsorship
has_sponsorship,
)
user = await app.get_users(holo_user.id)
@ -51,16 +93,17 @@ async def cmd_identify(app: Client, msg: Message):
if user.photo is not None:
await app.send_chat_action(msg.chat.id, action=ChatAction.UPLOAD_PHOTO)
await msg.reply_photo(
create_tmp((await download_tmp(app, user.photo.big_file_id))[1], kind="image"),
create_tmp(
(await download_tmp(app, user.photo.big_file_id))[1], kind="image"
),
quote=should_quote(msg),
caption=output
caption=output,
)
else:
await app.send_chat_action(msg.chat.id, action=ChatAction.TYPING)
await msg.reply_text(
output,
quote=should_quote(msg)
)
await msg.reply_text(output, quote=should_quote(msg))
logWrite(f"User {msg.from_user.id} identified user {holo_user.id}")
# ==============================================================================================================================

View File

@ -9,13 +9,28 @@ from classes.holo_user import HoloUser
# Issue command ================================================================================================================
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["issue"], prefixes=["/"]) & ~custom_filters.banned)
@app.on_message(
custom_filters.enabled_general
& ~filters.scheduled
& filters.private
& filters.command(["issue"], prefixes=["/"])
& ~custom_filters.banned
)
async def cmd_issue(app: Client, msg: Message):
await msg.reply_text(locale("issue", "message", locale=msg.from_user), disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup(
await msg.reply_text(
locale("issue", "message", locale=msg.from_user),
disable_web_page_preview=True,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("issue", "button", locale=msg.from_user), url=configGet("issues"))
InlineKeyboardButton(
locale("issue", "button", locale=msg.from_user),
url=configGet("issues"),
)
]
]
))
),
)
# ==============================================================================================================================

View File

@ -7,10 +7,15 @@ from classes.errors.holo_user import LabelTooLongError, LabelSettingError
from classes.holo_user import HoloUser
from modules import custom_filters
# Label command ================================================================================================================
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["label"], prefixes=["/"]) & custom_filters.admin)
async def cmd_label(app: Client, msg: Message):
# Label command ================================================================================================================
@app.on_message(
custom_filters.enabled_applications
& ~filters.scheduled
& filters.command(["label"], prefixes=["/"])
& custom_filters.admin
)
async def cmd_label(app: Client, msg: Message):
if len(msg.command) < 3:
await msg.reply_text("Invalid syntax:\n`/label USER LABEL`")
return
@ -18,14 +23,15 @@ async def cmd_label(app: Client, msg: Message):
target = await find_user(app, msg.command[1])
if target is not None:
target = HoloUser(target)
label = " ".join(msg.command[2:])
if label.lower() == "reset":
await target.label_reset(msg.chat)
await msg.reply_text(f"Resetting **{target.id}**'s label...", quote=should_quote(msg))
await msg.reply_text(
f"Resetting **{target.id}**'s label...", quote=should_quote(msg)
)
else:
try:
@ -34,10 +40,19 @@ async def cmd_label(app: Client, msg: Message):
await msg.reply_text(locale("label_too_long", "message"))
return
except LabelSettingError as exp:
await app.send_message(configGet("admin", "groups"), exp.__str__(), disable_notification=True)
await app.send_message(
configGet("admin", "groups"),
exp.__str__(),
disable_notification=True,
)
return
await msg.reply_text(f"Setting **{target.id}**'s label to **{label}**...", quote=should_quote(msg))
await msg.reply_text(
f"Setting **{target.id}**'s label to **{label}**...",
quote=should_quote(msg),
)
else:
await msg.reply_text(f"User not found")
# ==============================================================================================================================

View File

@ -7,28 +7,70 @@ from classes.holo_user import HoloUser
from modules.utils import logWrite, locale, should_quote, find_user
from modules import custom_filters
# Message command ==============================================================================================================
@app.on_message(custom_filters.enabled_general & ~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):
try:
try:
destination = HoloUser(int(msg.command[1]))
except (ValueError, UserInvalidError):
destination = HoloUser(await find_user(app, query=msg.command[1]))
if ((msg.text is not None) and (len(str(msg.text).split()) > 2)):
await destination.message(context=msg, text=" ".join(str(msg.text).split()[2:]), caption=msg.caption, photo=msg.photo, video=msg.video, file=msg.document, voice=msg.voice, animation=msg.animation, adm_context=True)
elif ((msg.caption is not None) and (len(msg.caption.split()) > 2)):
await destination.message(context=msg, text=str(msg.text), caption=" ".join(msg.caption.split()[2:]), photo=msg.photo, video=msg.video, file=msg.document, voice=msg.voice, animation=msg.animation, adm_context=True)
if (msg.text is not None) and (len(str(msg.text).split()) > 2):
await destination.message(
context=msg,
text=" ".join(str(msg.text).split()[2:]),
caption=msg.caption,
photo=msg.photo,
video=msg.video,
file=msg.document,
voice=msg.voice,
animation=msg.animation,
adm_context=True,
)
elif (msg.caption is not None) and (len(msg.caption.split()) > 2):
await destination.message(
context=msg,
text=str(msg.text),
caption=" ".join(msg.caption.split()[2:]),
photo=msg.photo,
video=msg.video,
file=msg.document,
voice=msg.voice,
animation=msg.animation,
adm_context=True,
)
else:
await destination.message(context=msg, text=None, caption=None, photo=msg.photo, video=msg.video, file=msg.document, voice=msg.voice, animation=msg.animation, adm_context=True)
await destination.message(
context=msg,
text=None,
caption=None,
photo=msg.photo,
video=msg.video,
file=msg.document,
voice=msg.voice,
animation=msg.animation,
adm_context=True,
)
except IndexError:
await msg.reply_text(locale("message_invalid_syntax", "message", locale=msg.from_user), quote=should_quote(msg))
await msg.reply_text(
locale("message_invalid_syntax", "message", locale=msg.from_user),
quote=should_quote(msg),
)
logWrite(f"Admin {msg.from_user.id} tried to send message but 'IndexError'")
except ValueError:
await msg.reply_text(locale("message_invalid_syntax", "message", locale=msg.from_user), quote=should_quote(msg))
await msg.reply_text(
locale("message_invalid_syntax", "message", locale=msg.from_user),
quote=should_quote(msg),
)
logWrite(f"Admin {msg.from_user.id} tried to send message but 'ValueError'")
# ==============================================================================================================================

View File

@ -11,50 +11,111 @@ from modules.utils import configGet, jsonLoad, locale, should_quote, find_locati
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", "groups")) | filters.chat(configGet("users", "groups")))) & filters.command(["nearby"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin) & ~custom_filters.banned)
async def cmd_nearby(app: Client, msg: Message):
# Nearby command ===============================================================================================================
@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)
& ~custom_filters.banned
)
async def cmd_nearby(app: Client, msg: Message):
holo_user = HoloUser(msg.from_user)
# Check if any place provided
if len(msg.command) == 1: # Action if no place provided
application = col_applications.find_one({"user": msg.from_user.id})
if application is None:
await msg.reply_text(locale("nearby_user_empty", "message", locale=holo_user))
await msg.reply_text(
locale("nearby_user_empty", "message", locale=holo_user)
)
return
location = application["application"]["3"]["location"][0], application["application"]["3"]["location"][1]
location = (
application["application"]["3"]["location"][0],
application["application"]["3"]["location"][1],
)
else: # Find a place from input query
logWrite(f"Looking for the location by query '{' '.join(msg.command[1:])}'")
try:
location_coordinates = find_location(" ".join(msg.command[1:]))
location = float(location_coordinates["lng"]), float(location_coordinates["lat"])
location = float(location_coordinates["lng"]), float(
location_coordinates["lat"]
)
except PlaceNotFoundError: # Place is not found
await msg.reply_text(locale("nearby_invalid", "message", locale=holo_user), quote=should_quote(msg))
await msg.reply_text(
locale("nearby_invalid", "message", locale=holo_user),
quote=should_quote(msg),
)
return
except Exception as exp: # Error occurred while finding the place
await msg.reply_text(locale("nearby_error", "message", locale=holo_user).format(exp, print_exc()), quote=should_quote(msg))
await msg.reply_text(
locale("nearby_error", "message", locale=holo_user).format(
exp, print_exc()
),
quote=should_quote(msg),
)
return
# Find all users registered in the area provided
output = []
applications_nearby = col_applications.find( {"application.3.location": { "$nearSphere": {"$geometry": {"type": "Point", "coordinates": [location[0], location[1]]}, "$maxDistance": configGet("search_radius")*1000} } } )
applications_nearby = col_applications.find(
{
"application.3.location": {
"$nearSphere": {
"$geometry": {
"type": "Point",
"coordinates": [location[0], location[1]],
},
"$maxDistance": configGet("search_radius") * 1000,
}
}
}
)
for entry in applications_nearby:
if not entry["user"] == msg.from_user.id:
user = col_users.find_one({"user": entry["user"]})
if user is not None:
if entry["user"] in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
if user["tg_username"] not in [None, "None", ""]: # Check if user has any name
output.append(f'• **{user["tg_name"]}** (@{user["tg_username"]}):\n - {entry["application"]["3"]["name"]}, {entry["application"]["3"]["adminName1"]}')
if entry["user"] in jsonLoad(
path.join(configGet("cache", "locations"), "group_members")
):
if user["tg_username"] not in [
None,
"None",
"",
]: # Check if user has any name
output.append(
f'• **{user["tg_name"]}** (@{user["tg_username"]}):\n - {entry["application"]["3"]["name"]}, {entry["application"]["3"]["adminName1"]}'
)
else:
output.append(f'• **{user["tg_name"]}**:\n - {entry["application"]["3"]["name"]}, {entry["application"]["3"]["adminName1"]}')
output.append(
f'• **{user["tg_name"]}**:\n - {entry["application"]["3"]["name"]}, {entry["application"]["3"]["adminName1"]}'
)
logWrite(f"{holo_user.id} tried to find someone nearby {location[1]} {location[0]} in the radius of {configGet('search_radius')} kilometers")
logWrite(
f"{holo_user.id} tried to find someone nearby {location[1]} {location[0]} in the radius of {configGet('search_radius')} kilometers"
)
# Check if any users found
if len(output) > 0:
await msg.reply_text(locale("nearby_result", "message", locale=holo_user).format("\n".join(output)), quote=should_quote(msg))
await msg.reply_text(
locale("nearby_result", "message", locale=holo_user).format(
"\n".join(output)
),
quote=should_quote(msg),
)
else:
await msg.reply_text(locale("nearby_empty", "message", locale=holo_user), quote=should_quote(msg))
await msg.reply_text(
locale("nearby_empty", "message", locale=holo_user), quote=should_quote(msg)
)
# ==============================================================================================================================

View File

@ -9,18 +9,32 @@ from modules.handlers.welcome import welcome_pass
from modules.database import col_tmp, col_applications
from modules import custom_filters
# Reapply command ==============================================================================================================
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(["reapply"], prefixes=["/"]) & ~custom_filters.banned)
async def cmd_reapply(app: Client, msg: Message):
# Reapply command ==============================================================================================================
@app.on_message(
custom_filters.enabled_applications
& ~filters.scheduled
& filters.private
& filters.command(["reapply"], prefixes=["/"])
& ~custom_filters.banned
)
async def cmd_reapply(app: Client, msg: Message):
holo_user = HoloUser(msg.from_user)
# Check if user has approved/rejected tmp application
if ((holo_user.application_state()[0] in ["approved", "rejected"]) or (holo_user.application_state()[0] == "none")) and holo_user.spoiler_state() is False:
if (
(holo_user.application_state()[0] in ["approved", "rejected"])
or (holo_user.application_state()[0] == "none")
) and holo_user.spoiler_state() is False:
# Check if user's tmp application is already completed or even sent
if ((holo_user.application_state()[1] is True) and (not col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"])) or (holo_user.application_state()[0] == "none"):
if (
(holo_user.application_state()[1] is True)
and (
not col_tmp.find_one({"user": holo_user.id, "type": "application"})[
"sent"
]
)
) or (holo_user.application_state()[0] == "none"):
left_chat = True
async for member in app.get_chat_members(configGet("users", "groups")):
@ -28,64 +42,132 @@ async def cmd_reapply(app: Client, msg: Message):
left_chat = False
if left_chat is True:
if (holo_user.application_state()[1] is True and holo_user.application_state()[0] not in ["fill", "rejected"]):
await msg.reply_text(locale("reapply_left_chat", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup([
if holo_user.application_state()[
1
] is True and holo_user.application_state()[0] not in [
"fill",
"rejected",
]:
await msg.reply_text(
locale("reapply_left_chat", "message", locale=holo_user),
reply_markup=InlineKeyboardMarkup(
[
InlineKeyboardButton(locale("reapply_old_one", "button", locale=holo_user), f"reapply_old_{msg.id}")
[
InlineKeyboardButton(
locale(
"reapply_old_one",
"button",
locale=holo_user,
),
f"reapply_old_{msg.id}",
)
],
[
InlineKeyboardButton(locale("reapply_new_one", "button", locale=holo_user), f"reapply_new_{msg.id}")
InlineKeyboardButton(
locale(
"reapply_new_one",
"button",
locale=holo_user,
),
f"reapply_new_{msg.id}",
)
],
]
]))
),
)
elif col_tmp.find_one({"user": holo_user.id, "type": "application"}) is None and col_applications.find_one({"user": holo_user.id}) is not None:
await msg.reply_text(locale("reapply_left_chat", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup([
elif (
col_tmp.find_one({"user": holo_user.id, "type": "application"})
is None
and col_applications.find_one({"user": holo_user.id}) is not None
):
await msg.reply_text(
locale("reapply_left_chat", "message", locale=holo_user),
reply_markup=InlineKeyboardMarkup(
[
InlineKeyboardButton(locale("reapply_old_one", "button", locale=holo_user), f"reapply_old_{msg.id}")
[
InlineKeyboardButton(
locale(
"reapply_old_one",
"button",
locale=holo_user,
),
f"reapply_old_{msg.id}",
)
],
[
InlineKeyboardButton(locale("reapply_new_one", "button", locale=holo_user), f"reapply_new_{msg.id}")
InlineKeyboardButton(
locale(
"reapply_new_one",
"button",
locale=holo_user,
),
f"reapply_new_{msg.id}",
)
],
]
]))
),
)
else:
holo_user.application_restart(reapply=True)
await welcome_pass(app, msg, once_again=True)
else:
if holo_user.sponsorship_state()[0] == "fill":
await msg.reply_text(locale("finish_sponsorship", "message"), quote=should_quote(msg))
await msg.reply_text(
locale("finish_sponsorship", "message"), quote=should_quote(msg)
)
return
holo_user.application_restart(reapply=True)
await welcome_pass(app, msg, once_again=True)
else:
await msg.reply_text(locale("reapply_in_progress", "message", locale=holo_user).format(locale("confirm", "keyboard", locale=holo_user)[1][0]), reply_markup=InlineKeyboardMarkup([
await msg.reply_text(
locale("reapply_in_progress", "message", locale=holo_user).format(
locale("confirm", "keyboard", locale=holo_user)[1][0]
),
reply_markup=InlineKeyboardMarkup(
[
InlineKeyboardButton(locale("applying_stop", "button", locale=holo_user), f"reapply_stop_{msg.id}")
[
InlineKeyboardButton(
locale("applying_stop", "button", locale=holo_user),
f"reapply_stop_{msg.id}",
)
]
]))
]
),
)
elif holo_user.spoiler_state() is True:
await msg.reply_text(locale("spoiler_in_progress", "message", locale=holo_user))
else:
if (holo_user.application_state()[0] == "fill") and (col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"] is True):
await msg.reply_text(locale("reapply_forbidden", "message", locale=holo_user))
if (holo_user.application_state()[0] == "fill") and (
col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"]
is True
):
await msg.reply_text(
locale("reapply_forbidden", "message", locale=holo_user)
)
else:
await msg.reply_text(locale("reapply_in_progress", "message", locale=holo_user).format(locale("confirm", "keyboard", locale=holo_user)[1][0]), reply_markup=InlineKeyboardMarkup([
await msg.reply_text(
locale("reapply_in_progress", "message", locale=holo_user).format(
locale("confirm", "keyboard", locale=holo_user)[1][0]
),
reply_markup=InlineKeyboardMarkup(
[
InlineKeyboardButton(locale("applying_stop", "button", locale=holo_user), f"reapply_stop_{msg.id}")
[
InlineKeyboardButton(
locale("applying_stop", "button", locale=holo_user),
f"reapply_stop_{msg.id}",
)
]
]))
]
),
)
# ==============================================================================================================================

View File

@ -11,14 +11,28 @@ from modules import custom_filters
pid = getpid()
# Reboot command ===============================================================================================================
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["/"]) & custom_filters.admin)
async def cmd_kill(app: Client, msg: Message):
# Reboot command ===============================================================================================================
@app.on_message(
custom_filters.enabled_general
& ~filters.scheduled
& filters.private
& filters.command(["kill", "die", "reboot"], prefixes=["/"])
& custom_filters.admin
)
async def cmd_kill(app: Client, msg: Message):
logWrite(f"Shutting down bot with pid {pid}")
await msg.reply_text(locale("shutdown", "message", locale=msg.from_user).format(pid), quote=should_quote(msg))
await msg.reply_text(
locale("shutdown", "message", locale=msg.from_user).format(pid),
quote=should_quote(msg),
)
scheduler.shutdown()
makedirs(configGet("cache", "locations"), exist_ok=True)
jsonSave({"timestamp": time()}, path.join(configGet("cache", "locations"), "shutdown_time"))
jsonSave(
{"timestamp": time()},
path.join(configGet("cache", "locations"), "shutdown_time"),
)
exit()
# ==============================================================================================================================

View File

@ -9,12 +9,17 @@ from modules import custom_filters
pid = getpid()
# Reset commands command =======================================================================================================
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["resetcommands"], prefixes=["/"]) & custom_filters.admin)
@app.on_message(
custom_filters.enabled_general
& ~filters.scheduled
& filters.private
& filters.command(["resetcommands"], prefixes=["/"])
& custom_filters.admin
)
async def cmd_resetcommands(app: Client, msg: Message):
if msg.from_user.id == configGet("owner"):
logWrite(f"Resetting all commands on owner's request")
valid_locales = []
@ -24,25 +29,45 @@ async def cmd_resetcommands(app: Client, msg: Message):
if entry.endswith(".json"):
valid_locales.append(".".join(entry.split(".")[:-1]))
logWrite(f'Resetting commands in groups {configGet("admin", "groups")} and {configGet("users", "groups")}', debug=True)
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")))
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("users", "groups")))
logWrite(
f'Resetting commands in groups {configGet("admin", "groups")} and {configGet("users", "groups")}',
debug=True,
)
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 lc in valid_locales:
try:
logWrite(f'Resetting commands in groups {configGet("admin", "groups")} and {configGet("users", "groups")} [{lc}]', debug=True)
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")), language_code=lc)
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("users", "groups")), language_code=lc)
logWrite(
f'Resetting commands in groups {configGet("admin", "groups")} and {configGet("users", "groups")} [{lc}]',
debug=True,
)
await app.delete_bot_commands(
scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")),
language_code=lc,
)
await app.delete_bot_commands(
scope=BotCommandScopeChat(chat_id=configGet("users", "groups")),
language_code=lc,
)
except:
pass
for admin in configGet("admins"):
try:
logWrite(f'Resetting commands for admin {admin}', debug=True)
logWrite(f"Resetting commands for admin {admin}", debug=True)
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=admin))
for lc in valid_locales:
try:
logWrite(f'Resetting commands for admin {admin} [{lc}]', debug=True)
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=admin), language_code=lc)
logWrite(
f"Resetting commands for admin {admin} [{lc}]", debug=True
)
await app.delete_bot_commands(
scope=BotCommandScopeChat(chat_id=admin), language_code=lc
)
except:
pass
except bad_request_400.PeerIdInvalid:
@ -51,21 +76,40 @@ async def cmd_resetcommands(app: Client, msg: Message):
try:
logWrite(f'Resetting commands for owner {configGet("owner")}', debug=True)
for lc in valid_locales:
logWrite(f'Resetting commands for owner {configGet("owner")} [{lc}]', debug=True)
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")))
logWrite(
f'Resetting commands for owner {configGet("owner")} [{lc}]',
debug=True,
)
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:
logWrite(f'Resetting commands for locale {lc}', debug=True)
await app.delete_bot_commands(scope=BotCommandScopeDefault(), language_code=lc)
logWrite(f"Resetting commands for locale {lc}", debug=True)
await app.delete_bot_commands(
scope=BotCommandScopeDefault(), language_code=lc
)
logWrite(f'Resetting default commands', debug=True)
logWrite(f"Resetting default commands", debug=True)
await app.delete_bot_commands()
await msg.reply_text("OK", quote=should_quote(msg))
logWrite(str(await app.get_bot_commands()), debug=True)
logWrite(str(await app.get_bot_commands(scope=BotCommandScopeChat(chat_id=configGet("owner")))), debug=True)
logWrite(
str(
await app.get_bot_commands(
scope=BotCommandScopeChat(chat_id=configGet("owner"))
)
),
debug=True,
)
# ==============================================================================================================================

View File

@ -7,36 +7,55 @@ from modules.utils import locale
from modules import custom_filters
from classes.holo_user import HoloUser
class DefaultRulesMarkup(list):
def __init__(self, language_code: Union[str, HoloUser, User, None]):
super().__init__([])
self.keyboard = InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("rules_home", "button", locale=language_code), callback_data="rules_home"),
InlineKeyboardButton(locale("rules_additional", "button", locale=language_code), callback_data="rules_additional")
InlineKeyboardButton(
locale("rules_home", "button", locale=language_code),
callback_data="rules_home",
),
InlineKeyboardButton(
locale("rules_additional", "button", locale=language_code),
callback_data="rules_additional",
),
],
[
InlineKeyboardButton("1", callback_data="rule_1"),
InlineKeyboardButton("2", callback_data="rule_2"),
InlineKeyboardButton("3", callback_data="rule_3")
InlineKeyboardButton("3", callback_data="rule_3"),
],
[
InlineKeyboardButton("4", callback_data="rule_4"),
InlineKeyboardButton("5", callback_data="rule_5"),
InlineKeyboardButton("6", callback_data="rule_6")
InlineKeyboardButton("6", callback_data="rule_6"),
],
[
InlineKeyboardButton("7", callback_data="rule_7"),
InlineKeyboardButton("8", callback_data="rule_8"),
InlineKeyboardButton("9", callback_data="rule_9")
]
InlineKeyboardButton("9", callback_data="rule_9"),
],
]
)
# Rules command =============================================================================================================
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & ~custom_filters.banned & filters.command(["rules"], prefixes=["/"]))
@app.on_message(
custom_filters.enabled_general
& ~filters.scheduled
& filters.private
& ~custom_filters.banned
& filters.command(["rules"], prefixes=["/"])
)
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

@ -9,24 +9,30 @@ from modules.utils import locale
from modules.database import col_spoilers, col_applications
from modules import custom_filters
# Spoiler command ==============================================================================================================
@app.on_message(custom_filters.enabled_spoilers & ~filters.scheduled & filters.private & ~custom_filters.banned & filters.command(["spoiler"], prefixes=["/"]))
async def cmd_spoiler(app: Client, msg: Message):
# Spoiler command ==============================================================================================================
@app.on_message(
custom_filters.enabled_spoilers
& ~filters.scheduled
& filters.private
& ~custom_filters.banned
& filters.command(["spoiler"], prefixes=["/"])
)
async def cmd_spoiler(app: Client, msg: Message):
try:
holo_user = HoloUser(msg.from_user)
except (UserInvalidError, UserNotFoundError):
return
if col_applications.find_one({"user": holo_user.id}) is None:
await msg.reply_text(locale("not_member", "message", locale=msg.from_user))
return
if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill":
if (
holo_user.application_state()[0] != "fill"
and holo_user.sponsorship_state()[0] != "fill"
):
if col_spoilers.find_one({"user": holo_user.id, "completed": False}) is None:
col_spoilers.insert_one(
{
"user": holo_user.id,
@ -39,13 +45,24 @@ async def cmd_spoiler(app: Client, msg: Message):
"animation": None,
"document": None,
"caption": None,
"text": None
"text": None,
}
)
await msg.reply_text(locale("spoiler_started", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_categories", "keyboard"), resize_keyboard=True, one_time_keyboard=True))
await msg.reply_text(
locale("spoiler_started", "message", locale=msg.from_user),
reply_markup=ReplyKeyboardMarkup(
locale("spoiler_categories", "keyboard"),
resize_keyboard=True,
one_time_keyboard=True,
),
)
logWrite(f"User {msg.from_user.id} started creating new spoiler")
else:
await msg.reply_text(locale("spoiler_unfinished", "message", locale=msg.from_user))
await msg.reply_text(
locale("spoiler_unfinished", "message", locale=msg.from_user)
)
# ==============================================================================================================================

View File

@ -7,17 +7,44 @@ from modules import custom_filters
from modules.utils import locale, should_quote
from modules.database import col_applications
# Sponsorship command ==========================================================================================================
@app.on_message(custom_filters.enabled_sponsorships & ~filters.scheduled & filters.command(["sponsorship"], prefixes=["/"]) & ~custom_filters.banned & (custom_filters.allowed | custom_filters.admin))
@app.on_message(
custom_filters.enabled_sponsorships
& ~filters.scheduled
& filters.command(["sponsorship"], prefixes=["/"])
& ~custom_filters.banned
& (custom_filters.allowed | custom_filters.admin)
)
async def cmd_sponsorship(app: Client, msg: Message):
holo_user = HoloUser(msg.from_user)
if holo_user.application_state()[0] == "fill":
await msg.reply_text(locale("finish_application", "message", locale=msg.from_user), quote=should_quote(msg))
await msg.reply_text(
locale("finish_application", "message", locale=msg.from_user),
quote=should_quote(msg),
)
return
if holo_user.spoiler_state() is True:
await msg.reply_text(locale("spoiler_in_progress", "message", locale=holo_user))
return
await msg.reply_text(locale("sponsorship_apply", "message", locale=msg.from_user), reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text=str(locale("sponsor_apply", "button", locale=msg.from_user)), callback_data=f"sponsor_apply_{msg.from_user.id}")]]), quote=should_quote(msg))
await msg.reply_text(
locale("sponsorship_apply", "message", locale=msg.from_user),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
text=str(
locale("sponsor_apply", "button", locale=msg.from_user)
),
callback_data=f"sponsor_apply_{msg.from_user.id}",
)
]
]
),
quote=should_quote(msg),
)
# else:
# await msg.reply_text(locale("sponsorship_application_empty", "message"))
# ==============================================================================================================================

View File

@ -8,42 +8,67 @@ 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=["/"]) & ~custom_filters.banned)
async def cmd_start(app: Client, msg: Message):
# Start command ================================================================================================================
@app.on_message(
custom_filters.enabled_applications
& ~filters.scheduled
& filters.private
& filters.command(["start"], prefixes=["/"])
& ~custom_filters.banned
)
async def cmd_start(app: Client, msg: Message):
user = col_users.find_one({"user": msg.from_user.id})
if user is None:
col_users.insert_one({
col_users.insert_one(
{
"user": msg.from_user.id,
"link": None,
"label": "",
"tg_name": msg.from_user.first_name,
"tg_phone": msg.from_user.phone_number,
"tg_locale": msg.from_user.language_code,
"tg_username": msg.from_user.username
})
"tg_username": msg.from_user.username,
}
)
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_cached_media(spoiler["photo"], caption=spoiler["caption"])
await msg.reply_cached_media(
spoiler["photo"], caption=spoiler["caption"]
)
if spoiler["video"] is not None:
await msg.reply_cached_media(spoiler["video"], caption=spoiler["caption"])
await msg.reply_cached_media(
spoiler["video"], caption=spoiler["caption"]
)
if spoiler["audio"] is not None:
await msg.reply_cached_media(spoiler["audio"], caption=spoiler["caption"])
await msg.reply_cached_media(
spoiler["audio"], caption=spoiler["caption"]
)
if spoiler["animation"] is not None:
await msg.reply_cached_media(spoiler["animation"], caption=spoiler["caption"])
await msg.reply_cached_media(
spoiler["animation"], caption=spoiler["caption"]
)
if spoiler["document"] is not None:
await msg.reply_cached_media(spoiler["document"], caption=spoiler["caption"])
await msg.reply_cached_media(
spoiler["document"], caption=spoiler["caption"]
)
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

@ -7,16 +7,41 @@ from modules.utils import configGet, locale
from modules.database import col_warnings
from modules import custom_filters
# Warn command =================================================================================================================
@app.on_message(custom_filters.enabled_warnings & ~filters.scheduled & filters.command(["warn"], prefixes=["/"]) & custom_filters.admin)
async def cmd_warn(app: Client, msg: Message):
# Warn command =================================================================================================================
@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("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})
col_warnings.insert_one(
{
"user": msg.reply_to_message.from_user.id,
"admin": msg.from_user.id,
"date": datetime.now(),
"reason": message,
}
)
if message == "":
await msg.reply_text(locale("warned", "message").format(msg.reply_to_message.from_user.first_name, msg.reply_to_message.from_user.id))
await msg.reply_text(
locale("warned", "message").format(
msg.reply_to_message.from_user.first_name,
msg.reply_to_message.from_user.id,
)
)
else:
await msg.reply_text(locale("warned_reason", "message").format(msg.reply_to_message.from_user.first_name, msg.reply_to_message.from_user.id, message))
await msg.reply_text(
locale("warned_reason", "message").format(
msg.reply_to_message.from_user.first_name,
msg.reply_to_message.from_user.id,
message,
)
)
# ==============================================================================================================================

View File

@ -7,12 +7,20 @@ from modules.utils import configGet, locale, should_quote
from modules.database import col_users, col_warnings
from modules import custom_filters
# Warnings command =============================================================================================================
@app.on_message(custom_filters.enabled_warnings & ~filters.scheduled & filters.command(["warnings"], prefixes=["/"]) & custom_filters.admin)
async def cmd_warnings(app: Client, msg: Message):
# Warnings command =============================================================================================================
@app.on_message(
custom_filters.enabled_warnings
& ~filters.scheduled
& filters.command(["warnings"], prefixes=["/"])
& custom_filters.admin
)
async def cmd_warnings(app: Client, msg: Message):
if len(msg.command) <= 1:
await msg.reply_text(locale("syntax_warnings", "message", locale=msg.from_user), quote=should_quote(msg))
await msg.reply_text(
locale("syntax_warnings", "message", locale=msg.from_user),
quote=should_quote(msg),
)
return
try:
@ -21,7 +29,11 @@ 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("users", "groups"), 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:
@ -29,16 +41,37 @@ async def cmd_warnings(app: Client, msg: Message):
target_name = target.first_name
target_id = str(target.id)
else:
await msg.reply_text(locale("no_user_warnings", "message", locale=msg.from_user).format(msg.command[1]))
await msg.reply_text(
locale("no_user_warnings", "message", locale=msg.from_user).format(
msg.command[1]
)
)
return
warns = len(list(col_warnings.find({"user": target_id})))
if warns == 0:
await msg.reply_text(locale("no_warnings", "message", locale=msg.from_user).format(target_name, target_id), quote=should_quote(msg))
await msg.reply_text(
locale("no_warnings", "message", locale=msg.from_user).format(
target_name, target_id
),
quote=should_quote(msg),
)
else:
if warns <= 5:
await msg.reply_text(locale("warnings_1", "message", locale=msg.from_user).format(target_name, target_id, warns), quote=should_quote(msg))
await msg.reply_text(
locale("warnings_1", "message", locale=msg.from_user).format(
target_name, target_id, warns
),
quote=should_quote(msg),
)
else:
await msg.reply_text(locale("warnings_2", "message", locale=msg.from_user).format(target_name, target_id, warns), quote=should_quote(msg))
await msg.reply_text(
locale("warnings_2", "message", locale=msg.from_user).format(
target_name, target_id, warns
),
quote=should_quote(msg),
)
# ==============================================================================================================================

View File

@ -12,13 +12,29 @@ 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
return (
True
if (
msg.from_user.id
in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))
)
else False
)
async def allowed_func(_, __, msg: Message):
output = False
output = True if (col_applications.find_one({"user": msg.from_user.id}) is not None) else False
if path.exists(path.join(configGet("cache", "locations"), "group_members")) and (msg.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))):
output = (
True
if (col_applications.find_one({"user": msg.from_user.id}) is not None)
else False
)
if path.exists(path.join(configGet("cache", "locations"), "group_members")) and (
msg.from_user.id
not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))
):
output = False
return output
@ -30,26 +46,39 @@ async def banned_func(_, __, msg: Message):
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 enabled_spoilers_func(_, __, msg: Message):
return configGet("enabled", "features", "spoilers")
async def filling_sponsorship_func(_, __, msg: Message):
return True if col_tmp.find_one({"user": msg.from_user.id, "type": "sponsorship"}) is not None else False
return (
True
if col_tmp.find_one({"user": msg.from_user.id, "type": "sponsorship"})
is not None
else False
)
admin = filters.create(admin_func)
member = filters.create(member_func)

View File

@ -9,18 +9,16 @@ with open("config.json", "r", encoding="utf-8") as f:
f.close()
if db_config["user"] is not None and db_config["password"] is not None:
con_string = 'mongodb://{0}:{1}@{2}:{3}/{4}'.format(
con_string = "mongodb://{0}:{1}@{2}:{3}/{4}".format(
db_config["user"],
db_config["password"],
db_config["host"],
db_config["port"],
db_config["name"]
db_config["name"],
)
else:
con_string = 'mongodb://{0}:{1}/{2}'.format(
db_config["host"],
db_config["port"],
db_config["name"]
con_string = "mongodb://{0}:{1}/{2}".format(
db_config["host"], db_config["port"], db_config["name"]
)
db_client = MongoClient(con_string)
@ -28,7 +26,18 @@ db = db_client.get_database(name=db_config["name"])
collections = db.list_collection_names()
for collection in ["tmp", "bans", "users", "context", "youtube", "spoilers", "messages", "warnings", "applications", "sponsorships"]:
for collection in [
"tmp",
"bans",
"users",
"context",
"youtube",
"spoilers",
"messages",
"warnings",
"applications",
"sponsorships",
]:
if not collection in collections:
db.create_collection(collection)

View File

@ -3,7 +3,13 @@ from dateutil.relativedelta import relativedelta
from datetime import datetime
from app import app
from pyrogram import filters
from pyrogram.types import ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton, ForceReply, Message
from pyrogram.types import (
ReplyKeyboardRemove,
InlineKeyboardMarkup,
InlineKeyboardButton,
ForceReply,
Message,
)
from pyrogram.client import Client
from pyrogram.enums.parse_mode import ParseMode
from classes.holo_user import HoloUser
@ -16,16 +22,30 @@ from modules import custom_filters
confirmation_1 = []
for pattern in all_locales("confirm", "keyboard"):
confirmation_1.append(pattern[0][0])
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.private & filters.command(confirmation_1, prefixes=[""]) & ~custom_filters.banned)
async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "sponsorship", "unknown"] = "unknown"):
@app.on_message(
(custom_filters.enabled_applications | custom_filters.enabled_sponsorships)
& ~filters.scheduled
& filters.private
& filters.command(confirmation_1, prefixes=[""])
& ~custom_filters.banned
)
async def confirm_yes(
app: Client,
msg: Message,
kind: Literal["application", "sponsorship", "unknown"] = "unknown",
):
holo_user = HoloUser(msg.from_user)
if configGet("enabled", "features", "applications") is True:
if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)):
tmp_application = col_tmp.find_one({"user": holo_user.id, "type": "application"})
if (kind == "application") or (
(holo_user.application_state()[0] == "fill")
and (holo_user.application_state()[1] is True)
):
tmp_application = col_tmp.find_one(
{"user": holo_user.id, "type": "application"}
)
if tmp_application is None:
logWrite(f"Application of {holo_user.id} is nowhere to be found.")
@ -34,73 +54,120 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
if tmp_application["sent"] is True:
return
await msg.reply_text(locale("application_sent", "message"), reply_markup=ReplyKeyboardRemove())
await msg.reply_text(
locale("application_sent", "message"),
reply_markup=ReplyKeyboardRemove(),
)
application_content = []
i = 1
for question in tmp_application['application']:
for question in tmp_application["application"]:
if i == 2:
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} р.)")
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} р.)"
)
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']}")
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']})")
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:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application'][question]}")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {tmp_application['application'][question]}"
)
i += 1
if tmp_application["reapply"] is True and col_applications.find_one({"user": holo_user.id}) is not None:
if (
tmp_application["reapply"] is True
and col_applications.find_one({"user": holo_user.id}) is not None
):
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)),
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:
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)),
text=(locale("application_got", "message")).format(
str(holo_user.id),
msg.from_user.first_name,
msg.from_user.username,
"\n".join(application_content),
),
parse_mode=ParseMode.MARKDOWN,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}")
InlineKeyboardButton(
text=str(locale("sub_yes", "button")),
callback_data=f"sub_yes_{holo_user.id}",
)
],
[
InlineKeyboardButton(text=str(locale("sub_no", "button")), callback_data=f"sub_no_{holo_user.id}")
InlineKeyboardButton(
text=str(locale("sub_no", "button")),
callback_data=f"sub_no_{holo_user.id}",
)
],
[
InlineKeyboardButton(text=str(locale("sub_russian", "button")), callback_data=f"sub_russian_{holo_user.id}")
]
]
InlineKeyboardButton(
text=str(locale("sub_russian", "button")),
callback_data=f"sub_russian_{holo_user.id}",
)
],
]
),
)
logWrite(f"User {holo_user.id} sent his application and it will now be reviewed")
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}})
col_tmp.update_one(
{"user": holo_user.id, "type": "application"}, {"$set": {"sent": True}}
)
return
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 (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.")
@ -109,58 +176,116 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
if tmp_sponsorship["sent"] is True:
return
await msg.reply_text(locale("sponsorship_sent", "message"), reply_markup=ReplyKeyboardRemove())
await msg.reply_text(
locale("sponsorship_sent", "message"),
reply_markup=ReplyKeyboardRemove(),
)
sponsorship_content = []
for question in tmp_sponsorship['sponsorship']:
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')}")
sponsorship_content.append(
f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question].strftime('%d.%m.%Y')}"
)
elif question == "proof":
continue
else:
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}")
sponsorship_content.append(
f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}"
)
await app.send_cached_media(configGet("admin", "groups"), tmp_sponsorship["sponsorship"]["proof"], caption=(locale("sponsor_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(sponsorship_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
await app.send_cached_media(
configGet("admin", "groups"),
tmp_sponsorship["sponsorship"]["proof"],
caption=(locale("sponsor_got", "message")).format(
str(holo_user.id),
msg.from_user.first_name,
msg.from_user.username,
"\n".join(sponsorship_content),
),
parse_mode=ParseMode.MARKDOWN,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(text=str(locale("sponsor_yes", "button")), callback_data=f"sponsor_yes_{holo_user.id}")
InlineKeyboardButton(
text=str(locale("sponsor_yes", "button")),
callback_data=f"sponsor_yes_{holo_user.id}",
)
],
[
InlineKeyboardButton(text=str(locale("sponsor_no", "button")), callback_data=f"sponsor_no_{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")
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}})
col_tmp.update_one(
{"user": holo_user.id, "type": "sponsorship"}, {"$set": {"sent": True}}
)
return
confirmation_2 = []
for pattern in all_locales("confirm", "keyboard"):
confirmation_2.append(pattern[1][0])
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.private & filters.command(confirmation_2, prefixes=[""]) & ~custom_filters.banned)
async def confirm_no(app: Client, msg: Message, kind: Literal["application", "sponsorship", "unknown"] = "unknown"):
@app.on_message(
(custom_filters.enabled_applications | custom_filters.enabled_sponsorships)
& ~filters.scheduled
& filters.private
& filters.command(confirmation_2, prefixes=[""])
& ~custom_filters.banned
)
async def confirm_no(
app: Client,
msg: Message,
kind: Literal["application", "sponsorship", "unknown"] = "unknown",
):
holo_user = HoloUser(msg.from_user)
if configGet("enabled", "features", "applications") is True:
if (kind == "application") or ((holo_user.application_state()[0] == "fill") and (holo_user.application_state()[1] is True)):
if (kind == "application") or (
(holo_user.application_state()[0] == "fill")
and (holo_user.application_state()[1] is True)
):
holo_user.application_restart()
await welcome_pass(app, msg, once_again=True)
logWrite(f"User {msg.from_user.id} restarted the application due to typo in it")
logWrite(
f"User {msg.from_user.id} restarted the application due to typo in it"
)
return
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)):
if (kind == "sponsorship") or (
(holo_user.sponsorship_state()[0] == "fill")
and (holo_user.sponsorship_state()[1] is True)
):
holo_user.sponsorship_restart()
await app.send_message(holo_user.id, locale(f"sponsor1", "message", locale=holo_user.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor1", "force_reply", locale=holo_user.locale))))
logWrite(f"User {msg.from_user.id} restarted the sponsorship application due to typo in it")
await app.send_message(
holo_user.id,
locale(f"sponsor1", "message", locale=holo_user.locale),
reply_markup=ForceReply(
placeholder=str(
locale(f"sponsor1", "force_reply", locale=holo_user.locale)
)
),
)
logWrite(
f"User {msg.from_user.id} restarted the sponsorship application due to typo in it"
)
return
# ==============================================================================================================================

View File

@ -9,46 +9,79 @@ from modules.database import col_applications
from classes.holo_user import HoloUser
from modules import custom_filters
# Contact getting ==============================================================================================================
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.contact & filters.private & (custom_filters.allowed | custom_filters.admin) & ~custom_filters.banned)
async def get_contact(app: Client, msg: Message):
# Contact getting ==============================================================================================================
@app.on_message(
custom_filters.enabled_applications
& ~filters.scheduled
& filters.contact
& filters.private
& (custom_filters.allowed | custom_filters.admin)
& ~custom_filters.banned
)
async def get_contact(app: Client, msg: Message):
holo_user = HoloUser(msg.from_user)
if msg.contact.user_id != None:
application = col_applications.find_one({"user": msg.contact.user_id})
if application is None:
logWrite(f"User {holo_user.id} requested application of {msg.contact.user_id} but user does not exists")
await msg.reply_text(locale("contact_invalid", "message", locale=holo_user.locale))
logWrite(
f"User {holo_user.id} requested application of {msg.contact.user_id} but user does not exists"
)
await msg.reply_text(
locale("contact_invalid", "message", locale=holo_user.locale)
)
return
application_content = []
i = 1
for question in application['application']:
for question in application["application"]:
if i == 2:
age = relativedelta(datetime.now(), application['application']['2'])
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
age = relativedelta(datetime.now(), application["application"]["2"])
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)"
)
elif i == 3:
if application['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['3']['name']}")
if application["application"]["3"]["countryCode"] == "UA":
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['3']['name']}"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application'][question]}")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=holo_user.locale)} {application['application'][question]}"
)
i += 1
application_status = locale("application_status_accepted", "message", locale=holo_user.locale).format((await app.get_users(application["admin"])).first_name, application["date"].strftime("%d.%m.%Y, %H:%M"))
application_status = locale(
"application_status_accepted", "message", locale=holo_user.locale
).format(
(await app.get_users(application["admin"])).first_name,
application["date"].strftime("%d.%m.%Y, %H:%M"),
)
logWrite(f"User {holo_user.id} requested application of {msg.contact.user_id}")
await msg.reply_text(locale("contact", "message", locale=holo_user.locale).format(str(msg.contact.user_id), "\n".join(application_content), application_status))
await msg.reply_text(
locale("contact", "message", locale=holo_user.locale).format(
str(msg.contact.user_id),
"\n".join(application_content),
application_status,
)
)
else:
logWrite(f"User {holo_user.id} requested application of someone but user is not telegram user")
await msg.reply_text(locale("contact_not_member", "message", locale=holo_user.locale))
logWrite(
f"User {holo_user.id} requested application of someone but user is not telegram user"
)
await msg.reply_text(
locale("contact_not_member", "message", locale=holo_user.locale)
)
# ==============================================================================================================================

View File

@ -3,35 +3,55 @@ from app import app, isAnAdmin
import asyncio
from ftfy import fix_text
from pyrogram import filters
from pyrogram.types import Message, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardRemove
from pyrogram.types import (
Message,
ForceReply,
InlineKeyboardMarkup,
InlineKeyboardButton,
ReplyKeyboardRemove,
)
from pyrogram.client import Client
from classes.holo_user import HoloUser
from modules.utils import configGet, logWrite, locale, all_locales
from modules.database import col_messages, col_spoilers
from modules import custom_filters
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,
}
)
if message is not None:
return True
return False
async def message_context(msg: Message) -> tuple:
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,
}
)
if message is not None:
return message["origin"]["chat"], message["origin"]["id"]
return 0, 0
# Any other input ==============================================================================================================
@app.on_message(~ filters.scheduled & (filters.private | filters.chat(configGet("admin", "groups"))) & ~custom_filters.banned)
@app.on_message(
~filters.scheduled
& (filters.private | filters.chat(configGet("admin", "groups")))
& ~custom_filters.banned
)
async def any_stage(app: Client, msg: Message):
if msg.via_bot is None:
holo_user = HoloUser(msg.from_user)
if (msg.reply_to_message is not None) and (await message_involved(msg)):
context = await message_context(msg)
context_message = await app.get_messages(context[0], context[1])
@ -51,7 +71,7 @@ async def any_stage(app: Client, msg: Message):
animation=msg.animation,
voice=msg.voice,
adm_origin=await isAnAdmin(context_message.from_user.id),
adm_context=await isAnAdmin(msg.from_user.id)
adm_context=await isAnAdmin(msg.from_user.id),
)
return
@ -60,29 +80,30 @@ async def any_stage(app: Client, msg: Message):
return
if msg.text is not None:
if configGet("enabled", "features", "applications") is True:
await holo_user.application_next(str(msg.text), msg=msg)
if configGet("enabled", "features", "sponsorships") is True:
await holo_user.sponsorship_next(str(msg.text), msg)
if msg.photo is not None:
await holo_user.sponsorship_next(str(msg.text), msg=msg, photo=msg.photo)
if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill":
if (
holo_user.application_state()[0] != "fill"
and holo_user.sponsorship_state()[0] != "fill"
):
if configGet("enabled", "features", "spoilers") is False:
return
spoiler = col_spoilers.find_one( {"user": msg.from_user.id, "completed": False} )
spoiler = col_spoilers.find_one(
{"user": msg.from_user.id, "completed": False}
)
if spoiler is None:
return
if spoiler["category"] is None:
found = False
# Find category in all locales
@ -93,86 +114,226 @@ async def any_stage(app: Client, msg: Message):
category = key
if found is False:
await msg.reply_text(locale("spoiler_incorrect_category", "message", locale=msg.from_user))
await msg.reply_text(
locale(
"spoiler_incorrect_category",
"message",
locale=msg.from_user,
)
)
return
col_spoilers.find_one_and_update( {"_id": spoiler["_id"]}, {"$set": {"category": category}} )
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
col_spoilers.find_one_and_update(
{"_id": spoiler["_id"]}, {"$set": {"category": category}}
)
await msg.reply_text(
locale("spoiler_send_description", "message", locale=msg.from_user),
reply_markup=ForceReply(
placeholder=locale(
"spoiler_description", "force_reply", locale=msg.from_user
)
),
)
return
if spoiler["description"] is None and (spoiler["photo"] is None and spoiler["video"] is None and spoiler["audio"] is None and spoiler["animation"] is None and spoiler["text"] is None):
if spoiler["description"] is None and (
spoiler["photo"] is None
and spoiler["video"] is None
and spoiler["audio"] is None
and spoiler["animation"] is None
and spoiler["text"] is None
):
# for lc in all_locales("spoiler_description", "keyboard"):
# if msg.text == lc[-1][0]:
# await msg.reply_text(locale("spoiler_description_enter", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
# return
if str(msg.text) != "-":
msg.text = fix_text(str(msg.text))
if len(str(msg.text)) > 1024:
await msg.reply_text(locale("spoiler_description_too_long", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
await msg.reply_text(
locale(
"spoiler_description_too_long",
"message",
locale=msg.from_user,
),
reply_markup=ForceReply(
placeholder=locale(
"spoiler_description",
"force_reply",
locale=msg.from_user,
)
),
)
return
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text}} )
col_spoilers.find_one_and_update(
{"user": msg.from_user.id, "completed": False},
{"$set": {"description": msg.text}},
)
else:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": ""}} )
col_spoilers.find_one_and_update(
{"user": msg.from_user.id, "completed": False},
{"$set": {"description": ""}},
)
logWrite(f"Adding description '{str(msg.text)}' to {msg.from_user.id}'s spoiler")
await msg.reply_text(locale("spoiler_using_description", "message", locale=msg.from_user).format(msg.text), reply_markup=ForceReply(placeholder=locale("spoiler_content", "force_reply", locale=msg.from_user)))
logWrite(
f"Adding description '{str(msg.text)}' to {msg.from_user.id}'s spoiler"
)
await msg.reply_text(
locale(
"spoiler_using_description", "message", locale=msg.from_user
).format(msg.text),
reply_markup=ForceReply(
placeholder=locale(
"spoiler_content", "force_reply", locale=msg.from_user
)
),
)
return
ready = False
if msg.photo is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"photo": msg.photo.file_id, "caption": msg.caption, "completed": True}} )
logWrite(f"Adding photo with id {msg.photo.file_id} to {msg.from_user.id}'s spoiler")
col_spoilers.find_one_and_update(
{"user": msg.from_user.id, "completed": False},
{
"$set": {
"photo": msg.photo.file_id,
"caption": msg.caption,
"completed": True,
}
},
)
logWrite(
f"Adding photo with id {msg.photo.file_id} to {msg.from_user.id}'s spoiler"
)
ready = True
if msg.video is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"video": msg.video.file_id, "caption": msg.caption, "completed": True}} )
logWrite(f"Adding audio with id {msg.video.file_id} to {msg.from_user.id}'s spoiler")
col_spoilers.find_one_and_update(
{"user": msg.from_user.id, "completed": False},
{
"$set": {
"video": msg.video.file_id,
"caption": msg.caption,
"completed": True,
}
},
)
logWrite(
f"Adding audio with id {msg.video.file_id} to {msg.from_user.id}'s spoiler"
)
ready = True
if msg.audio is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"audio": msg.audio.file_id, "caption": msg.caption, "completed": True}} )
logWrite(f"Adding video with id {msg.audio.file_id} to {msg.from_user.id}'s spoiler")
col_spoilers.find_one_and_update(
{"user": msg.from_user.id, "completed": False},
{
"$set": {
"audio": msg.audio.file_id,
"caption": msg.caption,
"completed": True,
}
},
)
logWrite(
f"Adding video with id {msg.audio.file_id} to {msg.from_user.id}'s spoiler"
)
ready = True
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, "caption": msg.caption, "completed": True}} )
logWrite(f"Adding animation with id {msg.animation.file_id} to {msg.from_user.id}'s spoiler")
col_spoilers.find_one_and_update(
{"user": msg.from_user.id, "completed": False},
{
"$set": {
"animation": msg.animation.file_id,
"caption": msg.caption,
"completed": True,
}
},
)
logWrite(
f"Adding animation with id {msg.animation.file_id} to {msg.from_user.id}'s spoiler"
)
ready = True
if msg.document is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"document": msg.document.file_id, "caption": msg.caption, "completed": True}} )
logWrite(f"Adding document with id {msg.document.file_id} to {msg.from_user.id}'s spoiler")
col_spoilers.find_one_and_update(
{"user": msg.from_user.id, "completed": False},
{
"$set": {
"document": msg.document.file_id,
"caption": msg.caption,
"completed": True,
}
},
)
logWrite(
f"Adding document with id {msg.document.file_id} to {msg.from_user.id}'s spoiler"
)
ready = True
if spoiler["photo"] is None and spoiler["video"] is None and spoiler["audio"] is None and spoiler["animation"] is None and spoiler["document"] is None and spoiler["text"] is None:
if (
spoiler["photo"] is None
and spoiler["video"] is None
and spoiler["audio"] is None
and spoiler["animation"] is None
and spoiler["document"] is None
and spoiler["text"] is None
):
if msg.text is not None:
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"text": str(msg.text), "completed": True}} )
logWrite(f"Adding text '{str(msg.text)}' to {msg.from_user.id}'s spoiler")
col_spoilers.find_one_and_update(
{"user": msg.from_user.id, "completed": False},
{"$set": {"text": str(msg.text), "completed": True}},
)
logWrite(
f"Adding text '{str(msg.text)}' to {msg.from_user.id}'s spoiler"
)
ready = True
if ready is True:
await msg.reply_text(locale("spoiler_ready", "message", locale=msg.from_user), reply_markup=ReplyKeyboardRemove())
await msg.reply_text(
locale("spoiler_ready", "message", locale=msg.from_user),
reply_markup=ReplyKeyboardRemove(),
)
if configGet("allow_external", "features", "spoilers") is True:
await msg.reply_text(
locale("spoiler_send", "message", locale=msg.from_user),
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("spoiler_preview", "button", locale=msg.from_user), callback_data=f"sid_{spoiler['_id'].__str__()}")
],
[
InlineKeyboardButton(locale("spoiler_send_chat", "button", locale=msg.from_user), callback_data=f"shc_{spoiler['_id'].__str__()}")
],
[
InlineKeyboardButton(locale("spoiler_send_other", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")
]
]
InlineKeyboardButton(
locale(
"spoiler_preview",
"button",
locale=msg.from_user,
),
callback_data=f"sid_{spoiler['_id'].__str__()}",
)
],
[
InlineKeyboardButton(
locale(
"spoiler_send_chat",
"button",
locale=msg.from_user,
),
callback_data=f"shc_{spoiler['_id'].__str__()}",
)
],
[
InlineKeyboardButton(
locale(
"spoiler_send_other",
"button",
locale=msg.from_user,
),
switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}",
)
],
]
),
)
else:
await msg.reply_text(
@ -180,33 +341,65 @@ async def any_stage(app: Client, msg: Message):
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(locale("spoiler_preview", "button", locale=msg.from_user), callback_data=f"sid_{spoiler['_id'].__str__()}")
InlineKeyboardButton(
locale(
"spoiler_preview",
"button",
locale=msg.from_user,
),
callback_data=f"sid_{spoiler['_id'].__str__()}",
)
],
[
InlineKeyboardButton(locale("spoiler_send_chat", "button", locale=msg.from_user), callback_data=f"shc_{spoiler['_id'].__str__()}")
]
]
InlineKeyboardButton(
locale(
"spoiler_send_chat",
"button",
locale=msg.from_user,
),
callback_data=f"shc_{spoiler['_id'].__str__()}",
)
],
]
),
)
else:
await msg.reply_text(locale("spoiler_incorrect_content", "message", locale=msg.from_user))
await msg.reply_text(
locale("spoiler_incorrect_content", "message", locale=msg.from_user)
)
@app.on_message(~filters.scheduled & filters.group)
async def message_in_group(app: Client, msg: Message):
if (msg.chat is not None) and (msg.via_bot is not None):
if (msg.via_bot.id == (await app.get_me()).id) and (msg.chat.id == configGet("users", "groups")):
if str(msg.text).startswith(locale("spoiler_described", "message").split()[0]) or str(msg.text).startswith(locale("spoiler_empty", "message").split()[0]):
if (msg.via_bot.id == (await app.get_me()).id) and (
msg.chat.id == configGet("users", "groups")
):
if str(msg.text).startswith(
locale("spoiler_described", "message").split()[0]
) or str(msg.text).startswith(
locale("spoiler_empty", "message").split()[0]
):
logWrite(f"User {msg.from_user.id} sent spoiler to user's group")
try:
logWrite("Forwarding spoiler to admin's group")
await msg.copy(configGet("admin", "groups"), disable_notification=True)
await msg.copy(
configGet("admin", "groups"), disable_notification=True
)
except Exception as exp:
logWrite(f"Could not forward spoiler to admin's group due to '{exp}': {print_exc()}")
logWrite(
f"Could not forward spoiler to admin's group due to '{exp}': {print_exc()}"
)
return
if configGet("remove_application_time") > 0:
logWrite(f"User {msg.from_user.id} requested application in destination group, removing in {configGet('remove_application_time')} minutes")
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 msg.delete()
logWrite(f"Removed application requested by {msg.from_user.id} in destination group")
logWrite(
f"Removed application requested by {msg.from_user.id} in destination group"
)
# ==============================================================================================================================

View File

@ -1,6 +1,11 @@
from datetime import datetime
from app import app, isAnAdmin
from pyrogram.types import ChatPermissions, InlineKeyboardMarkup, InlineKeyboardButton, ChatMemberUpdated
from pyrogram.types import (
ChatPermissions,
InlineKeyboardMarkup,
InlineKeyboardButton,
ChatMemberUpdated,
)
from pyrogram.client import Client
from modules.utils import configGet, locale
from modules import custom_filters
@ -9,45 +14,64 @@ from modules.database import col_applications
from classes.holo_user import HoloUser
from dateutil.relativedelta import relativedelta
# Filter users on join =========================================================================================================
@app.on_chat_member_updated(custom_filters.enabled_invites_check, group=configGet("users", "groups"))
@app.on_chat_member_updated(
custom_filters.enabled_invites_check, group=configGet("users", "groups")
)
# @app.on_message(filters.new_chat_members, group=configGet("users", "groups"))
async def filter_join(app: Client, member: ChatMemberUpdated):
if member.invite_link != None:
holo_user = HoloUser(member.from_user)
if (holo_user.link is not None) and (holo_user.link == member.invite_link.invite_link):
logWrite(f"User {holo_user.id} joined destination group with correct link {holo_user.link}")
if (holo_user.link is not None) and (
holo_user.link == member.invite_link.invite_link
):
logWrite(
f"User {holo_user.id} joined destination group with correct link {holo_user.link}"
)
application = col_applications.find_one({"user": holo_user.id})
application_content = []
i = 1
for question in application['application']:
for question in application["application"]:
if i == 2:
age = relativedelta(datetime.now(), application['application']['2'])
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
age = relativedelta(datetime.now(), application["application"]["2"])
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)"
)
elif i == 3:
if application['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']}")
if application["application"]["3"]["countryCode"] == "UA":
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']}"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application'][question]}")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {application['application'][question]}"
)
i += 1
await app.send_message(configGet("users", "groups"), locale("joined_application", "message").format(member.from_user.first_name, member.from_user.username, "\n".join(application_content)))
await app.send_message(
configGet("users", "groups"),
locale("joined_application", "message").format(
member.from_user.first_name,
member.from_user.username,
"\n".join(application_content),
),
)
return
if await isAnAdmin(member.invite_link.creator.id):
logWrite(f"User {holo_user.id} joined destination group with link {holo_user.link} of an admin {member.invite_link.creator.id}")
logWrite(
f"User {holo_user.id} joined destination group with link {holo_user.link} of an admin {member.invite_link.creator.id}"
)
application = col_applications.find_one({"user": holo_user.id})
@ -57,42 +81,75 @@ async def filter_join(app: Client, member: ChatMemberUpdated):
application_content = []
i = 1
for question in application['application']:
for question in application["application"]:
if i == 2:
age = relativedelta(datetime.now(), application['application']['2'])
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
age = relativedelta(datetime.now(), application["application"]["2"])
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)"
)
elif i == 3:
if application['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']}")
if application["application"]["3"]["countryCode"] == "UA":
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']}"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles')} {application['application'][question]}")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles')} {application['application'][question]}"
)
i += 1
await app.send_message(configGet("users", "groups"), locale("joined_application", "message").format(member.from_user.first_name, member.from_user.username, "\n".join(application_content)))
await app.send_message(
configGet("users", "groups"),
locale("joined_application", "message").format(
member.from_user.first_name,
member.from_user.username,
"\n".join(application_content),
),
)
return
logWrite(f"User {holo_user.id} joined destination group with stolen/unapproved link {holo_user.link}")
logWrite(
f"User {holo_user.id} joined destination group with stolen/unapproved link {holo_user.link}"
)
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(
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}",
)
],
[
InlineKeyboardButton(text=str(locale("sus_reject", "button")), callback_data=f"sus_reject_{member.from_user.id}")
InlineKeyboardButton(
text=str(locale("sus_reject", "button")),
callback_data=f"sus_reject_{member.from_user.id}",
)
],
]
]
))
await app.restrict_chat_member(member.chat.id, member.from_user.id, permissions=ChatPermissions(
),
)
await app.restrict_chat_member(
member.chat.id,
member.from_user.id,
permissions=ChatPermissions(
can_send_messages=False,
can_send_media_messages=False,
can_send_other_messages=False,
can_send_polls=False
)
can_send_polls=False,
),
)
# ==============================================================================================================================

View File

@ -7,7 +7,13 @@ 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("users", "groups")))
@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

@ -12,7 +12,15 @@ for pattern in all_locales("welcome", "keyboard"):
welcome_1.append(pattern[0][0])
for pattern in all_locales("return", "keyboard"):
welcome_1.append(pattern[0][0])
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(welcome_1, prefixes=[""]) & ~custom_filters.banned)
@app.on_message(
custom_filters.enabled_applications
& ~filters.scheduled
& filters.private
& filters.command(welcome_1, prefixes=[""])
& ~custom_filters.banned
)
async def welcome_pass(app: Client, msg: Message, once_again: bool = False) -> None:
"""Set user's stage to 1 and start a fresh application
@ -33,15 +41,37 @@ async def welcome_pass(app: Client, msg: Message, once_again: bool = False) -> N
if once_again is True:
logWrite(f"User {msg.from_user.id} confirmed starting the application")
else:
logWrite(f"User {msg.from_user.id} confirmed starting the application once again")
await msg.reply_text(locale("question1", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("question1", "force_reply", locale=msg.from_user)))
logWrite(
f"User {msg.from_user.id} confirmed starting the application once again"
)
await msg.reply_text(
locale("question1", "message", locale=msg.from_user),
reply_markup=ForceReply(
placeholder=locale("question1", "force_reply", locale=msg.from_user)
),
)
welcome_2 = []
for pattern in all_locales("welcome", "keyboard"):
welcome_2.append(pattern[1][0])
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(welcome_2, prefixes=[""]) & ~custom_filters.banned)
async def welcome_reject(app: Client, msg: Message):
@app.on_message(
custom_filters.enabled_applications
& ~filters.scheduled
& filters.private
& filters.command(welcome_2, prefixes=[""])
& ~custom_filters.banned
)
async def welcome_reject(app: Client, msg: Message):
logWrite(f"User {msg.from_user.id} rejected to start the application")
await msg.reply_text(locale("goodbye", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("return", "keyboard", locale=msg.from_user), resize_keyboard=True))
await msg.reply_text(
locale("goodbye", "message", locale=msg.from_user),
reply_markup=ReplyKeyboardMarkup(
locale("return", "keyboard", locale=msg.from_user), resize_keyboard=True
),
)
# ==============================================================================================================================

View File

@ -4,7 +4,13 @@ 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, InlineKeyboardMarkup, InlineKeyboardButton
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
@ -17,39 +23,74 @@ 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 configGet("allow_external", "features", "spoilers") is True:
if inline_query.query.startswith("spoiler:"):
try:
spoil = col_spoilers.find_one( {"_id": ObjectId(inline_query.query.removeprefix("spoiler:"))} )
spoil = col_spoilers.find_one(
{"_id": ObjectId(inline_query.query.removeprefix("spoiler:"))}
)
if spoil is not None:
desc = locale("spoiler_empty", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories")) if spoil["description"] == "" else locale("spoiler_described", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), spoil["description"])
desc = (
locale(
"spoiler_empty", "message", locale=inline_query.from_user
).format(
locale(spoil["category"], "message", "spoiler_categories")
)
if spoil["description"] == ""
else locale(
"spoiler_described",
"message",
locale=inline_query.from_user,
).format(
locale(spoil["category"], "message", "spoiler_categories"),
spoil["description"],
)
)
results = [
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:")}')]])
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
)
await inline_query.answer(results=results)
return
@ -57,11 +98,20 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
await inline_query.answer(
results=[
InlineQueryResultArticle(
title=locale("title", "inline", "not_pm", locale=inline_query.from_user),
input_message_content=InputTextMessageContent(
locale("message_content", "inline", "not_pm", locale=inline_query.from_user)
title=locale(
"title", "inline", "not_pm", locale=inline_query.from_user
),
input_message_content=InputTextMessageContent(
locale(
"message_content",
"inline",
"not_pm",
locale=inline_query.from_user,
)
),
description=locale(
"description", "inline", "not_pm", locale=inline_query.from_user
),
description=locale("description", "inline", "not_pm", locale=inline_query.from_user)
)
]
)
@ -71,39 +121,59 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
InlineQueryResultArticle(
title=locale("title", "inline", "forbidden", locale=inline_query.from_user),
input_message_content=InputTextMessageContent(
locale("message_content", "inline", "forbidden", locale=inline_query.from_user)
locale(
"message_content",
"inline",
"forbidden",
locale=inline_query.from_user,
)
),
description=locale(
"description", "inline", "forbidden", locale=inline_query.from_user
),
description=locale("description", "inline", "forbidden", locale=inline_query.from_user)
)
]
try:
holo_user = HoloUser(inline_query.from_user)
except (UserNotFoundError, UserInvalidError):
logWrite(f"Could not find application of {inline_query.from_user.id}, ignoring inline query", debug=True)
await inline_query.answer(
results=results_forbidden
logWrite(
f"Could not find application of {inline_query.from_user.id}, ignoring inline query",
debug=True,
)
await inline_query.answer(results=results_forbidden)
return
if path.exists(path.join(configGet("cache", "locations"), "group_members")) and (inline_query.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))):
if path.exists(path.join(configGet("cache", "locations"), "admins")) and (inline_query.from_user.id not in jsonLoad(path.join(configGet("cache", "locations"), "admins"))):
logWrite(f"{inline_query.from_user.id} is not an admin and not in members group, ignoring inline query", debug=True)
await inline_query.answer(
results=results_forbidden
if path.exists(path.join(configGet("cache", "locations"), "group_members")) and (
inline_query.from_user.id
not in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))
):
if path.exists(path.join(configGet("cache", "locations"), "admins")) and (
inline_query.from_user.id
not in jsonLoad(path.join(configGet("cache", "locations"), "admins"))
):
logWrite(
f"{inline_query.from_user.id} is not an admin and not in members group, ignoring inline query",
debug=True,
)
await inline_query.answer(results=results_forbidden)
return
if holo_user.application_approved() or (await isAnAdmin(holo_user.id) is True):
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 = []
async for m in app.get_chat_members(configGet("users", "groups"), 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)
for match in list_of_users:
application = col_applications.find_one({"user": match.user.id})
if application is None:
@ -112,34 +182,63 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
application_content = []
i = 1
for question in application['application']:
for question in application["application"]:
if i == 2:
age = relativedelta(datetime.now(), application['application']['2'])
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)")
age = relativedelta(datetime.now(), application["application"]["2"])
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['2'].strftime('%d.%m.%Y')} ({age.years} р.)"
)
elif i == 3:
if application['application']['3']['countryCode'] == "UA":
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['3']['name']}")
if application["application"]["3"]["countryCode"] == "UA":
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['3']['name']}"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application']['3']['name']} ({application['application']['3']['adminName1']}, {application['application']['3']['countryName']})"
)
else:
application_content.append(f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application'][question]}")
application_content.append(
f"{locale(f'question{i}', 'message', 'question_titles', locale=inline_query.from_user)} {application['application'][question]}"
)
i += 1
if match.user.photo != None:
try:
if not path.exists(f'{configGet("cache", "locations")}{sep}avatars{sep}{match.user.photo.big_file_id}'):
print(f'Downloaded avatar {match.user.photo.big_file_id} of {match.user.id} and uploaded to {configGet("api")}/?avatar_id={match.user.photo.big_file_id}', flush=True)
await app.download_media(match.user.photo.big_file_id, file_name=f'{configGet("cache", "locations")}{sep}avatars{sep}{match.user.photo.big_file_id}')
if not path.exists(
f'{configGet("cache", "locations")}{sep}avatars{sep}{match.user.photo.big_file_id}'
):
print(
f'Downloaded avatar {match.user.photo.big_file_id} of {match.user.id} and uploaded to {configGet("api")}/?avatar_id={match.user.photo.big_file_id}',
flush=True,
)
await app.download_media(
match.user.photo.big_file_id,
file_name=f'{configGet("cache", "locations")}{sep}avatars{sep}{match.user.photo.big_file_id}',
)
results.append(
InlineQueryResultArticle(
title=str(match.user.first_name),
input_message_content=InputTextMessageContent(
locale("message_content", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username, "\n".join(application_content))
locale(
"message_content",
"inline",
"user",
locale=inline_query.from_user,
).format(
match.user.first_name,
match.user.username,
"\n".join(application_content),
)
),
description=locale("description", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username),
thumb_url=f'{configGet("api")}/?avatar_id={match.user.photo.big_file_id}'
description=locale(
"description",
"inline",
"user",
locale=inline_query.from_user,
).format(match.user.first_name, match.user.username),
thumb_url=f'{configGet("api")}/?avatar_id={match.user.photo.big_file_id}',
)
)
except ValueError:
@ -147,9 +246,23 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
InlineQueryResultArticle(
title=str(match.user.first_name),
input_message_content=InputTextMessageContent(
locale("message_content", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username, "\n".join(application_content))
locale(
"message_content",
"inline",
"user",
locale=inline_query.from_user,
).format(
match.user.first_name,
match.user.username,
"\n".join(application_content),
)
),
description=locale("description", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username)
description=locale(
"description",
"inline",
"user",
locale=inline_query.from_user,
).format(match.user.first_name, match.user.username),
)
)
except FileNotFoundError:
@ -157,9 +270,23 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
InlineQueryResultArticle(
title=str(match.user.first_name),
input_message_content=InputTextMessageContent(
locale("message_content", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username, "\n".join(application_content))
locale(
"message_content",
"inline",
"user",
locale=inline_query.from_user,
).format(
match.user.first_name,
match.user.username,
"\n".join(application_content),
)
),
description=locale("description", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username)
description=locale(
"description",
"inline",
"user",
locale=inline_query.from_user,
).format(match.user.first_name, match.user.username),
)
)
else:
@ -167,14 +294,24 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
InlineQueryResultArticle(
title=str(match.user.first_name),
input_message_content=InputTextMessageContent(
locale("message_content", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username, "\n".join(application_content))
locale(
"message_content",
"inline",
"user",
locale=inline_query.from_user,
).format(
match.user.first_name,
match.user.username,
"\n".join(application_content),
)
),
description=locale("description", "inline", "user", locale=inline_query.from_user).format(match.user.first_name, match.user.username)
description=locale(
"description",
"inline",
"user",
locale=inline_query.from_user,
).format(match.user.first_name, match.user.username),
)
)
await inline_query.answer(
results=results,
cache_time=10,
is_personal=True
)
await inline_query.answer(results=results, cache_time=10, is_personal=True)

View File

@ -5,12 +5,13 @@ from shutil import copyfileobj
from datetime import datetime
with open(getcwd()+path.sep+"config.json", "r", encoding='utf8') as file:
with open(getcwd() + path.sep + "config.json", "r", encoding="utf8") as file:
json_contents = loads(file.read())
log_size = json_contents["logging"]["size"]
log_folder = json_contents["logging"]["location"]
file.close()
# Check latest log size
def checkSize(debug=False):
"""Check size of latest.log file and rotate it if needed
@ -30,15 +31,24 @@ def checkSize(debug=False):
makedirs(log_folder, exist_ok=True)
log = stat(path.join(log_folder, log_file))
if (log.st_size / 1024) > log_size:
with open(path.join(log_folder, log_file), 'rb') as f_in:
with gzipopen(path.join(log_folder, f'{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.log.gz'), 'wb') as f_out:
with open(path.join(log_folder, log_file), "rb") as f_in:
with gzipopen(
path.join(
log_folder,
f'{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.log.gz',
),
"wb",
) as f_out:
copyfileobj(f_in, f_out)
print(f'Copied {path.join(log_folder, datetime.now().strftime("%d.%m.%Y_%H:%M:%S"))}.log.gz')
open(path.join(log_folder, log_file), 'w').close()
print(
f'Copied {path.join(log_folder, datetime.now().strftime("%d.%m.%Y_%H:%M:%S"))}.log.gz'
)
open(path.join(log_folder, log_file), "w").close()
except FileNotFoundError:
print(f'Log file {path.join(log_folder, log_file)} does not exist')
print(f"Log file {path.join(log_folder, log_file)} does not exist")
pass
# Append string to log
def logAppend(message: str, debug=False):
"""Write message to log file
@ -58,10 +68,11 @@ def logAppend(message: str, debug=False):
else:
log_file = "latest.log"
log = open(path.join(log_folder, log_file), 'a')
log.write(f'{message_formatted}\n')
log = open(path.join(log_folder, log_file), "a")
log.write(f"{message_formatted}\n")
log.close()
# Print to stdout and then to log
def logWrite(message: str, debug=False):
"""Write message to stdout and log file
@ -71,5 +82,5 @@ def logWrite(message: str, debug=False):
* debug (`bool`, *optional*): Whether this is a debug log. Defaults to `False`.
"""
# save to log file and rotation is to be done
logAppend(f'{message}', debug=debug)
logAppend(f"{message}", debug=debug)
print(f"{message}", flush=True)

View File

@ -8,7 +8,11 @@ from apscheduler.schedulers.asyncio import AsyncIOScheduler
from datetime import datetime, timedelta
from ujson import dumps
from app import app
from pyrogram.types import BotCommand, BotCommandScopeChat, BotCommandScopeChatAdministrators
from pyrogram.types import (
BotCommand,
BotCommandScopeChat,
BotCommandScopeChatAdministrators,
)
from pyrogram.errors import bad_request_400
from pyrogram.enums.chat_members_filter import ChatMembersFilter
from classes.holo_user import HoloUser
@ -21,18 +25,27 @@ from requests import get
scheduler = AsyncIOScheduler()
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():
list_of_users = []
async for member in app.get_chat_members(configGet("users", "groups")):
list_of_users.append(member.user.id)
makedirs(configGet("cache", "locations"), exist_ok=True)
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "group_members"))
jsonSave(
list_of_users, path.join(configGet("cache", "locations"), "group_members")
)
if configGet("debug") is True:
logWrite("User group caching performed", debug=True)
if configGet("enabled", "scheduler", "cache_admins"):
@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():
list_of_users = []
async for member in app.get_chat_members(configGet("admin", "groups")):
@ -42,37 +55,66 @@ if configGet("enabled", "scheduler", "cache_admins"):
if configGet("debug") is True:
logWrite("Admin group caching performed", debug=True)
# Cache the avatars of group members
if configGet("enabled", "scheduler", "cache_avatars"):
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=15))
@scheduler.scheduled_job(trigger="interval", hours=configGet("interval", "scheduler", "cache_avatars"))
@scheduler.scheduled_job(
trigger="date", run_date=datetime.now() + timedelta(seconds=15)
)
@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("users", "groups"), 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:
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)
await app.download_media(user.photo.big_file_id, file_name=path.join(configGet("cache", "locations"), "avatars", 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,
)
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")
# Check for birthdays
if configGet("enabled", "features", "applications") is True:
if configGet("enabled", "scheduler", "birthdays") is True:
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "birthdays"))
@scheduler.scheduled_job(
trigger="cron", hour=configGet("time", "scheduler", "birthdays")
)
async def check_birthdays():
for entry in col_applications.find():
if entry["application"]["2"].strftime("%d.%m") == datetime.now().strftime("%d.%m"):
if entry["application"]["2"].strftime(
"%d.%m"
) == datetime.now().strftime("%d.%m"):
try:
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
if entry["user"] not in jsonLoad(
path.join(configGet("cache", "locations"), "group_members")
):
continue
tg_user = await app.get_users(entry["user"])
await app.send_message( configGet("admin", "groups"), locale("birthday", "message").format(str(tg_user.first_name), str(tg_user.username), str(relativedelta(datetime.now(), entry["application"]["2"], '%d.%m.%Y').years)) ) # type: ignore
await app.send_message(configGet("admin", "groups"), locale("birthday", "message").format(str(tg_user.first_name), str(tg_user.username), str(relativedelta(datetime.now(), entry["application"]["2"], "%d.%m.%Y").years))) # type: ignore
logWrite(f"Notified admins about {entry['user']}'s birthday")
except Exception as exp:
logWrite(f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'")
logWrite(
f"Could not find user {entry['user']} to send a message about birthday due to '{exp}'"
)
continue
logWrite("Birthdays check performed")
@ -80,42 +122,71 @@ if configGet("enabled", "features", "applications") is True:
# Check for expired sponsorships
if configGet("enabled", "features", "sponsorships") is True:
if configGet("enabled", "scheduler", "sponsorships") is True:
@scheduler.scheduled_job(trigger="cron", hour=configGet("time", "scheduler", "sponsorships"))
@scheduler.scheduled_job(
trigger="cron", hour=configGet("time", "scheduler", "sponsorships")
)
async def check_sponsors():
for entry in col_sponsorships.find({"sponsorship.expires": {"$lt": datetime.now()+timedelta(days=2)}}):
for entry in col_sponsorships.find(
{"sponsorship.expires": {"$lt": datetime.now() + timedelta(days=2)}}
):
try:
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
if entry["user"] not in jsonLoad(
path.join(configGet("cache", "locations"), "group_members")
):
continue
tg_user = await app.get_users(entry["user"])
until_expiry = abs(relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days)+1
until_expiry = (
abs(
relativedelta(
datetime.now(), entry["sponsorship"]["expires"]
).days
)
+ 1
)
await app.send_message(tg_user.id, locale("sponsorships_expires", "message").format(until_expiry)) # type: ignore
logWrite(f"Notified user {entry['user']} that sponsorship expires in {until_expiry} days")
logWrite(
f"Notified user {entry['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}'")
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()-timedelta(days=1)}}):
for entry in col_sponsorships.find(
{"sponsorship.expires": {"$lt": datetime.now() - timedelta(days=1)}}
):
try:
holo_user = HoloUser(entry["user"])
col_sponsorships.find_one_and_delete({"user": holo_user.id})
if entry["user"] not in jsonLoad(path.join(configGet("cache", "locations"), "group_members")):
if entry["user"] not in jsonLoad(
path.join(configGet("cache", "locations"), "group_members")
):
continue
await app.send_message(entry["user"], locale("sponsorships_expired", "message")) # type: ignore
await holo_user.label_reset(configGet("users", "groups"))
try:
tg_user = await app.get_users(entry["user"])
logWrite(f"Notified user {entry['user']} that sponsorship expired")
logWrite(
f"Notified user {entry['user']} that sponsorship expired"
)
except Exception as exp:
logWrite(f"Could not find user {entry['user']} notify about sponsorship expired due to '{exp}'")
logWrite(
f"Could not find user {entry['user']} notify about sponsorship expired due to '{exp}'"
)
except Exception as exp:
logWrite(f"Could not reset label of user {entry['user']} due to '{exp}'")
logWrite(
f"Could not reset label of user {entry['user']} due to '{exp}'"
)
continue
logWrite("Sponsorships check performed")
# Register all bot commands
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=10))
@scheduler.scheduled_job(
trigger="date", run_date=datetime.now() + timedelta(seconds=10)
)
async def commands_register():
commands = {
"users": [],
"admins": [],
@ -123,7 +194,7 @@ async def commands_register():
"group_users": [],
"group_admins": [],
"group_users_admins": [],
"locales": {}
"locales": {},
}
commands_raw = {
@ -133,7 +204,7 @@ async def commands_register():
"group_users": [],
"group_admins": [],
"group_users_admins": [],
"locales": {}
"locales": {},
}
valid_locales = []
@ -148,7 +219,7 @@ async def commands_register():
"owner": [],
"group_users": [],
"group_admins": [],
"group_users_admins": []
"group_users_admins": [],
}
if configGet("debug") is True:
commands_raw["locales"][".".join(entry.split(".")[:-1])] = {
@ -157,15 +228,13 @@ async def commands_register():
"owner": [],
"group_users": [],
"group_admins": [],
"group_users_admins": []
"group_users_admins": [],
}
config_modules = configGet("features")
config_commands = configGet("commands")
for command in config_commands:
enabled = False
for module in config_commands[command]["modules"]:
@ -177,22 +246,27 @@ async def commands_register():
continue
for permission in config_commands[command]["permissions"]:
commands[permission].append(BotCommand(command, locale("commands")[command]))
commands[permission].append(
BotCommand(command, locale("commands")[command])
)
if configGet("debug") is True:
commands_raw[permission].append({f"{command}": locale("commands")[command]})
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]))
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]})
commands_raw["locales"][lc][permission].append(
{f"{command}": locale("commands", locale=lc)[command]}
)
logWrite(f"Registering {command} for {permission} [{lc}]")
# Registering user commands
await app.set_bot_commands(commands["users"])
logWrite("Registered user commands for default locale")
@ -205,55 +279,94 @@ async def commands_register():
# Registering admin commands
for admin in configGet("admins"):
try:
await app.set_bot_commands(commands["admins"]+commands["users"], 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}")
except bad_request_400.PeerIdInvalid:
pass
# Registering owner commands
try:
await app.set_bot_commands(commands["admins"]+commands["owner"]+commands["users"], 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")))
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')}")
except bad_request_400.PeerIdInvalid:
pass
# Registering admin group commands
try:
await app.set_bot_commands(commands["group_admins"], scope=BotCommandScopeChat(chat_id=configGet("admin", "groups")))
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.")
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("users", "groups")))
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.")
logWrite(
f"Could not register commands for destination group. Bot is likely not in the group."
)
# Registering destination group admin commands
try:
await app.set_bot_commands(commands["group_users_admins"], scope=BotCommandScopeChatAdministrators(chat_id=configGet("users", "groups")))
await app.set_bot_commands(
commands["group_users_admins"],
scope=BotCommandScopeChatAdministrators(
chat_id=configGet("users", "groups")
),
)
logWrite("Registered destination group admin commands")
except bad_request_400.ChannelInvalid:
logWrite(f"Could not register admin commands for destination group. Bot is likely not in the group.")
logWrite(
f"Could not register admin 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)}", debug=True)
logWrite(
f"Complete commands registration:\n{dumps(commands_raw, indent=4, ensure_ascii=False, encode_html_chars=False)}",
debug=True,
)
if configGet("enabled", "scheduler", "channels_monitor"):
@scheduler.scheduled_job(trigger="interval", minutes=configGet("interval", "scheduler", "channels_monitor"))
@scheduler.scheduled_job(
trigger="interval",
minutes=configGet("interval", "scheduler", "channels_monitor"),
)
async def channels_monitor():
for channel in configGet("channels", "scheduler", "channels_monitor"):
if configGet("debug") is True:
logWrite(f'Processing videos of {channel["name"]} ({channel["id"]})', debug=True)
logWrite(
f'Processing videos of {channel["name"]} ({channel["id"]})',
debug=True,
)
try:
req = get(f'https://www.youtube.com/feeds/videos.xml?channel_id={channel["id"]}')
req = get(
f'https://www.youtube.com/feeds/videos.xml?channel_id={channel["id"]}'
)
parsed = parse(req.content)
if "feed" not in parsed:
continue
@ -262,11 +375,33 @@ if configGet("enabled", "scheduler", "channels_monitor"):
for entry in parsed["feed"]["entry"]:
if "yt:videoId" not in entry:
continue
if col_youtube.find_one( {"channel": channel["id"], "video": entry["yt:videoId"]} ) is None:
col_youtube.insert_one( {"channel": channel["id"], "video": entry["yt:videoId"], "date": datetime.fromisoformat(entry["published"])} )
await app.send_message(configGet("users", "groups"), locale("youtube_video", "message").format(channel["name"], channel["link"], entry["title"], entry["link"]["@href"]), disable_web_page_preview=False)
if (
col_youtube.find_one(
{"channel": channel["id"], "video": entry["yt:videoId"]}
)
is None
):
col_youtube.insert_one(
{
"channel": channel["id"],
"video": entry["yt:videoId"],
"date": datetime.fromisoformat(entry["published"]),
}
)
await app.send_message(
configGet("users", "groups"),
locale("youtube_video", "message").format(
channel["name"],
channel["link"],
entry["title"],
entry["link"]["@href"],
),
disable_web_page_preview=False,
)
await sleep(2)
except Exception as exp:
logWrite(f'Could not get last videos of {channel["name"]} ({channel["id"]}) due to {exp}: {format_exc()}')
logWrite(
f'Could not get last videos of {channel["name"]} ({channel["id"]}) due to {exp}: {format_exc()}'
)
if configGet("debug") is True:
logWrite("Admin group caching performed", debug=True)

View File

@ -16,23 +16,29 @@ from classes.errors.geo import PlaceNotFoundError
from modules.logging import logWrite
def jsonLoad(filename):
"""Loads arg1 as json and returns its contents"""
with open(filename, "r", encoding='utf8') as file:
with open(filename, "r", encoding="utf8") as file:
try:
output = loads(file.read())
except JSONDecodeError:
logWrite(f"Could not load json file {filename}: file seems to be incorrect!\n{print_exc()}")
logWrite(
f"Could not load json file {filename}: file seems to be incorrect!\n{print_exc()}"
)
raise
except FileNotFoundError:
logWrite(f"Could not load json file {filename}: file does not seem to exist!\n{print_exc()}")
logWrite(
f"Could not load json file {filename}: file does not seem to exist!\n{print_exc()}"
)
raise
return output
def jsonSave(contents, filename):
"""Dumps dict/list arg1 to file arg2"""
try:
with open(filename, "w", encoding='utf8') as file:
with open(filename, "w", encoding="utf8") as file:
file.write(dumps(contents, ensure_ascii=False, indent=4))
except Exception as exp:
logWrite(f"Could not save json file {filename}: {exp}\n{print_exc()}")
@ -52,6 +58,7 @@ def nested_set(dic, keys, value, create_missing=True):
d[keys[-1]] = value
return dic
def configSet(keys: list, value: Any, file: str = "config", create_missing=True):
"""Set config's value to provided one
@ -69,7 +76,10 @@ def configSet(keys: list, value: Any, file: str = "config", create_missing=True)
this_dict = jsonLoad("config_debug.json")
file = "config_debug"
except FileNotFoundError:
print("Debug mode is set but config_debug.json is not there! Falling back to config.json", flush=True)
print(
"Debug mode is set but config_debug.json is not there! Falling back to config.json",
flush=True,
)
else:
filepath = f"data{sep}users{sep}"
this_dict = jsonLoad(f"{filepath}{file}.json")
@ -78,6 +88,7 @@ def configSet(keys: list, value: Any, file: str = "config", create_missing=True)
jsonSave(this_dict, f"{filepath}{file}.json")
return
def configGet(key: str, *args: str, file: str = "config"):
"""Get value of the config key
### Args:
@ -91,13 +102,19 @@ def configGet(key: str, *args: str, file: str = "config"):
try:
this_dict = jsonLoad("config.json")
except FileNotFoundError:
print("Config file not found! Copy config_example.json to config.json, configure it and rerun the bot!", flush=True)
print(
"Config file not found! Copy config_example.json to config.json, configure it and rerun the bot!",
flush=True,
)
exit()
if this_dict["debug"] is True:
try:
this_dict = jsonLoad("config_debug.json")
except FileNotFoundError:
print("Debug mode is set but config_debug.json is not there! Falling back to config.json", flush=True)
print(
"Debug mode is set but config_debug.json is not there! Falling back to config.json",
flush=True,
)
else:
this_dict = jsonLoad(f"data{sep}users{sep}{file}.json")
this_key = this_dict
@ -105,6 +122,7 @@ def configGet(key: str, *args: str, file: str = "config"):
this_key = this_key[dict_key]
return this_key[key]
def locale(key: str, *args: str, locale: Union[str, User] = configGet("locale")) -> Any:
"""Get value of locale string
### Args:
@ -126,7 +144,9 @@ def locale(key: str, *args: str, locale: Union[str, User] = configGet("locale"))
this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{locale}.json')
except FileNotFoundError:
try:
this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{configGet("locale")}.json')
this_dict = jsonLoad(
f'{configGet("locale", "locations")}{sep}{configGet("locale")}.json'
)
except FileNotFoundError:
return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
@ -139,6 +159,7 @@ def locale(key: str, *args: str, locale: Union[str, User] = configGet("locale"))
except KeyError:
return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
def all_locales(key: str, *args: str) -> list:
"""Get value of the provided key and path in all available locales
@ -174,6 +195,7 @@ def all_locales(key: str, *args: str) -> list:
return output
def find_location(query: str) -> dict:
"""Find location on geonames.org by query. Search is made with feature classes A and P.
@ -187,12 +209,20 @@ def find_location(query: str) -> dict:
* `dict`: One instance of geonames response
"""
try:
result = (get(f"http://api.geonames.org/searchJSON?q={query}&maxRows=1&countryBias=UA&lang=uk&orderby=relevance&featureClass=P&featureClass=A&username={configGet('username', 'geocoding')}")).json()
result = (
get(
f"http://api.geonames.org/searchJSON?q={query}&maxRows=1&countryBias=UA&lang=uk&orderby=relevance&featureClass=P&featureClass=A&username={configGet('username', 'geocoding')}"
)
).json()
return result["geonames"][0]
except (ValueError, KeyError, IndexError):
raise PlaceNotFoundError(query)
def create_tmp(bytedata: Union[bytes, bytearray], kind: Union[Literal["image", "video"], None] = None) -> str:
def create_tmp(
bytedata: Union[bytes, bytearray],
kind: Union[Literal["image", "video"], None] = None,
) -> str:
"""Create temporary file to help uploading it
### Args:
@ -212,6 +242,7 @@ def create_tmp(bytedata: Union[bytes, bytearray], kind: Union[Literal["image", "
file.write(bytedata)
return path.join("tmp", filename)
async def download_tmp(app: Client, file_id: str) -> Tuple[str, bytes]:
"""Download file by its ID and return its bytes
@ -229,24 +260,31 @@ async def download_tmp(app: Client, file_id: str) -> Tuple[str, bytes]:
bytedata = f.read()
return path.join("tmp", filename), bytedata
try:
from psutil import Process
except ModuleNotFoundError:
# print(locale("deps_missing", "console", locale=configGet("locale")), flush=True)
print("Missing dependencies! Please install all needed dependencies and run the bot again!")
print(
"Missing dependencies! Please install all needed dependencies and run the bot again!"
)
exit()
def killProc(pid):
if osname == "posix":
from signal import SIGKILL
kill(pid, SIGKILL)
else:
p = Process(pid)
p.kill()
def should_quote(msg):
return True if msg.chat.type is not ChatType.PRIVATE else False
async def find_user(app: Client, query: Union[str, int]):
try:
result = await app.get_users(int(query))