Compare commits
61 Commits
6b80b7d0fa
...
v.1.2
Author | SHA1 | Date | |
---|---|---|---|
95be1e72d3 | |||
ecbf7d8b78 | |||
92386ac8ce | |||
dabfa2ecef | |||
00a408ac6c | |||
b67b1daf7c | |||
f83751c07d | |||
f5e3cd5a50 | |||
478fb174c5 | |||
30dfe4ff04 | |||
bdc775dcbd | |||
717d636497 | |||
64b0562bc4 | |||
eced1b7984 | |||
da3dd3a2fe | |||
3e166a3fca | |||
d090b18655 | |||
e2d28f442c | |||
496240c48b | |||
|
0bf5ae70eb | ||
|
bcaf80e2e1 | ||
|
21bf460b28 | ||
|
a4bbb837d7 | ||
|
1a438fc32e | ||
234b73add0 | |||
742b529c33 | |||
78a37ca186 | |||
374effd5d7 | |||
|
1195df894c | ||
|
67f1ce535f | ||
|
b6d45545fc | ||
|
59dafc004d | ||
|
57518399a1 | ||
|
ee288a1983 | ||
373f2332a0 | |||
f4fb85f7a4 | |||
02a6960391 | |||
7939f8b65e | |||
5b28f9f588 | |||
6e44177907 | |||
4f0b9f8e3a | |||
78dee0591c | |||
b0b0f04a9b | |||
9e009aea43 | |||
42d00383bf | |||
4fba305b05 | |||
47e62946ab | |||
68c7cc0ada | |||
646db667d9 | |||
2e8277d6d2 | |||
19fc9308e4 | |||
c90495eb1c | |||
|
bdb2338ab9 | ||
|
496bb7d4a6 | ||
|
b437092fe7 | ||
|
9431763e6b | ||
|
4977b8f31a | ||
|
0739eeb87d | ||
|
0214a29a2e | ||
79304816b0 | |||
2cfa5a8f8d |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -161,4 +161,6 @@ data
|
||||
TASK.md
|
||||
inline_bot.py
|
||||
.vscode
|
||||
migrate.py
|
||||
migrate.py
|
||||
validation/*
|
||||
!validation/*.json
|
28
README.md
28
README.md
@@ -72,13 +72,16 @@ You can see config file with all the comments below:
|
||||
"enabled": true
|
||||
},
|
||||
"warnings": {
|
||||
"enabled": false
|
||||
"enabled": true
|
||||
},
|
||||
"invites_check": {
|
||||
"enabled": true
|
||||
},
|
||||
"dinovoice": {
|
||||
"enabled": false
|
||||
},
|
||||
"spoilers": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"scheduler": {
|
||||
@@ -117,12 +120,22 @@ You can see config file with all the comments below:
|
||||
"general"
|
||||
]
|
||||
},
|
||||
"spoiler": {
|
||||
"permissions": [
|
||||
"users",
|
||||
"admins"
|
||||
],
|
||||
"modules": [
|
||||
"spoilers"
|
||||
]
|
||||
},
|
||||
"cancel": {
|
||||
"permissions": [
|
||||
"users",
|
||||
"admins"
|
||||
],
|
||||
"modules": [
|
||||
"spoilers",
|
||||
"applications",
|
||||
"sponsorships"
|
||||
]
|
||||
@@ -166,8 +179,7 @@ You can see config file with all the comments below:
|
||||
},
|
||||
"reboot": {
|
||||
"permissions": [
|
||||
"admins",
|
||||
"group_admins"
|
||||
"owner"
|
||||
],
|
||||
"modules": [
|
||||
"general"
|
||||
@@ -218,6 +230,14 @@ You can see config file with all the comments below:
|
||||
"modules": [
|
||||
"applications"
|
||||
]
|
||||
},
|
||||
"resetcommands": {
|
||||
"permissions": [
|
||||
"owner"
|
||||
],
|
||||
"modules": [
|
||||
"general"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,7 +249,7 @@ After all of that you're good to go! Happy using :)
|
||||
|
||||
* [ ] Stats and infographics
|
||||
* [ ] Check group members without completed application
|
||||
* [ ] Replicate some functions of @spoilerobot
|
||||
* [x] Replicate some functions of @spoilerobot
|
||||
* [x] Check sponsorship on Holo girls
|
||||
* [x] /nearby command
|
||||
* [x] Complete messenger between user and admins
|
||||
|
24
classes/errors/holo_user.py
Normal file
24
classes/errors/holo_user.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""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")
|
||||
|
||||
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")
|
||||
|
||||
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)")
|
||||
|
||||
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```")
|
@@ -1,75 +1,18 @@
|
||||
from datetime import datetime
|
||||
from traceback import print_exc
|
||||
from asyncio import sleep
|
||||
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.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.templates import DefaultApplicationTemp, DefaultSponsorshipTemp
|
||||
from modules.database import col_tmp, col_users, col_applications, col_sponsorships, col_messages, col_spoilers
|
||||
from modules.logging import logWrite
|
||||
from modules.utils import configGet, create_tmp, download_tmp, find_location, locale, should_quote
|
||||
|
||||
class DefaultApplicationTemp(dict):
|
||||
def __init__(self, user: int, reapply: bool = False):
|
||||
super().__init__({})
|
||||
self.dict = {
|
||||
"user": user,
|
||||
"type": "application",
|
||||
"complete": False,
|
||||
"sent": False,
|
||||
"state": "fill",
|
||||
"reapply": reapply,
|
||||
"stage": 1,
|
||||
"application": {
|
||||
"1": None,
|
||||
"2": None,
|
||||
"3": None,
|
||||
"4": None,
|
||||
"5": None,
|
||||
"6": None,
|
||||
"7": None,
|
||||
"8": None,
|
||||
"9": None,
|
||||
"10": None
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultSponsorshipTemp(dict):
|
||||
def __init__(self, user: int):
|
||||
super().__init__({})
|
||||
self.dict = {
|
||||
"user": user,
|
||||
"type": "sponsorship",
|
||||
"complete": False,
|
||||
"sent": False,
|
||||
"state": "fill",
|
||||
"stage": 1,
|
||||
"sponsorship": {
|
||||
"streamer": None,
|
||||
"expires": datetime.fromtimestamp(0),
|
||||
"proof": None,
|
||||
"label": ""
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
|
||||
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")
|
||||
|
||||
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)")
|
||||
from modules.utils import configGet, find_location, locale, should_quote
|
||||
|
||||
class HoloUser():
|
||||
"""This object represents a user of HoloChecker bot.
|
||||
@@ -180,13 +123,18 @@ class HoloUser():
|
||||
* adm_context (`bool`, *optional*): Whether context sender is an admin. Defaults to False.
|
||||
"""
|
||||
|
||||
if text is not None:
|
||||
text = fix_text(text)
|
||||
elif caption is not None:
|
||||
caption = fix_text(caption)
|
||||
|
||||
# Check if any text available and log message sending
|
||||
if text is not None:
|
||||
logWrite(f"{context.from_user.id} sent message '{text}' to {self.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}")
|
||||
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}")
|
||||
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:
|
||||
@@ -215,19 +163,19 @@ class HoloUser():
|
||||
if photo is not None:
|
||||
if isinstance(photo, Photo):
|
||||
photo = photo.file_id
|
||||
new_message = await origin.reply_photo(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_video(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_document(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_animation(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
|
||||
@@ -240,23 +188,23 @@ class HoloUser():
|
||||
if photo is not None:
|
||||
if isinstance(photo, Photo):
|
||||
photo = photo.file_id
|
||||
new_message = await app.send_photo(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_video(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_document(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_animation(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_voice(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)
|
||||
|
||||
@@ -266,9 +214,9 @@ class HoloUser():
|
||||
|
||||
# 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{print_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, print_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))
|
||||
@@ -286,12 +234,12 @@ class HoloUser():
|
||||
try:
|
||||
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)
|
||||
self.set("label", label)
|
||||
except bad_request_400.UserCreator:
|
||||
logWrite(f"Could not set {self.id}'s title to '{self.label}' because of bad_request_400.UserCreator")
|
||||
except bad_request_400.ChatAdminRequired:
|
||||
logWrite(f"Could not set {self.id}'s title to '{self.label}' because of bad_request_400.ChatAdminRequired")
|
||||
except Exception as exp:
|
||||
logWrite(f"Could not set {self.id}'s title to '{self.label}' due to {exp}")
|
||||
raise LabelSettingError(exp, format_exc())
|
||||
|
||||
async def label_reset(self, chat: Chat) -> None:
|
||||
"""Reset label in destination group
|
||||
@@ -333,10 +281,9 @@ class HoloUser():
|
||||
"""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).dict)
|
||||
else:
|
||||
col_tmp.delete_one({"user": self.id, "type": "application"})
|
||||
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)
|
||||
|
||||
async def application_next(self, query: str, msg: Message) -> None:
|
||||
"""Move on filling application of user
|
||||
@@ -371,6 +318,9 @@ class HoloUser():
|
||||
|
||||
if progress["state"] == "fill" and progress["sent"] is False:
|
||||
|
||||
if msg.text is not None:
|
||||
msg.text = fix_text(msg.text)
|
||||
|
||||
if stage == 2:
|
||||
|
||||
try:
|
||||
@@ -391,7 +341,6 @@ class HoloUser():
|
||||
return
|
||||
|
||||
else:
|
||||
print(f'Look: {((datetime.now() - input_dt).days)} > {(datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days}')
|
||||
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))))
|
||||
@@ -412,12 +361,15 @@ class HoloUser():
|
||||
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))))
|
||||
try:
|
||||
await app.send_message(configGet("owner"), locale("question3_traceback", "message", locale=self.locale).format(query, exp, print_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!")
|
||||
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))))
|
||||
return
|
||||
progress["application"][str(stage)] = query
|
||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "complete": True}})
|
||||
application_content = []
|
||||
@@ -437,6 +389,9 @@ class HoloUser():
|
||||
await msg.reply_text(locale("confirm", "message", locale=self.locale).format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard", locale=self.locale), resize_keyboard=True))
|
||||
|
||||
else:
|
||||
if len(query) > 256:
|
||||
await msg.reply_text(locale("question_too_long", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"question{stage}", "force_reply", locale=self.locale))))
|
||||
return
|
||||
progress["application"][str(stage)] = query
|
||||
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))))
|
||||
@@ -483,19 +438,26 @@ class HoloUser():
|
||||
* msg (`Message`): Message that should receive replies
|
||||
"""
|
||||
|
||||
if col_tmp.find_one({"user": self.id, "type": "sponsorship"}) is not None:
|
||||
progress = col_tmp.find_one({"user": self.id, "type": "sponsorship"})
|
||||
|
||||
progress = col_tmp.find_one({"user": self.id, "type": "sponsorship"})
|
||||
|
||||
if progress is None:
|
||||
return
|
||||
if progress is not None:
|
||||
|
||||
stage = progress["stage"]
|
||||
|
||||
if msg.text is not None:
|
||||
msg.text = fix_text(msg.text)
|
||||
elif msg.caption is not None:
|
||||
msg.caption = fix_text(msg.caption)
|
||||
|
||||
if progress["state"] == "fill" and progress["sent"] is False:
|
||||
|
||||
if stage == 1:
|
||||
|
||||
if len(query) > 240:
|
||||
logWrite(f"User {msg.from_user.id} failed stage {stage} due to sending invalid date format")
|
||||
await msg.reply_text(locale(f"sponsor1_invalid", "message", locale=self.locale), reply_markup=ForceReply(placeholder=str(locale(f"sponsor{stage}", "force_reply", locale=self.locale))))
|
||||
return
|
||||
|
||||
progress["sponsorship"]["streamer"] = query
|
||||
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))))
|
||||
@@ -522,7 +484,7 @@ class HoloUser():
|
||||
elif stage == 3:
|
||||
|
||||
if photo is not None:
|
||||
progress["sponsorship"]["proof"] = await download_tmp(app, photo.file_id)
|
||||
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))))
|
||||
|
||||
@@ -532,8 +494,8 @@ class HoloUser():
|
||||
return
|
||||
progress["sponsorship"]["label"] = query
|
||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "complete": True}})
|
||||
await msg.reply_photo(
|
||||
photo=create_tmp(progress["sponsorship"]["proof"], kind="image"),
|
||||
await msg.reply_cached_media(
|
||||
progress["sponsorship"]["proof"],
|
||||
caption=locale("sponsor_confirm", "message", locale=self.locale).format(
|
||||
progress["sponsorship"]["streamer"],
|
||||
progress["sponsorship"]["expires"].strftime("%d.%m.%Y"),
|
||||
|
46
classes/templates.py
Normal file
46
classes/templates.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""Templates for temporary application/sponsorship records"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
class DefaultApplicationTemp(dict):
|
||||
def __init__(self, user: int, reapply: bool = False):
|
||||
super().__init__({})
|
||||
self.dict = {
|
||||
"user": user,
|
||||
"type": "application",
|
||||
"complete": False,
|
||||
"sent": False,
|
||||
"state": "fill",
|
||||
"reapply": reapply,
|
||||
"stage": 1,
|
||||
"application": {
|
||||
"1": None,
|
||||
"2": None,
|
||||
"3": None,
|
||||
"4": None,
|
||||
"5": None,
|
||||
"6": None,
|
||||
"7": None,
|
||||
"8": None,
|
||||
"9": None,
|
||||
"10": None
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultSponsorshipTemp(dict):
|
||||
def __init__(self, user: int):
|
||||
super().__init__({})
|
||||
self.dict = {
|
||||
"user": user,
|
||||
"type": "sponsorship",
|
||||
"complete": False,
|
||||
"sent": False,
|
||||
"state": "fill",
|
||||
"stage": 1,
|
||||
"sponsorship": {
|
||||
"streamer": None,
|
||||
"expires": datetime.fromtimestamp(0),
|
||||
"proof": None,
|
||||
"label": ""
|
||||
}
|
||||
}
|
@@ -42,13 +42,16 @@
|
||||
"enabled": true
|
||||
},
|
||||
"warnings": {
|
||||
"enabled": false
|
||||
"enabled": true
|
||||
},
|
||||
"invites_check": {
|
||||
"enabled": true
|
||||
},
|
||||
"dinovoice": {
|
||||
"enabled": false
|
||||
},
|
||||
"spoilers": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"scheduler": {
|
||||
@@ -91,6 +94,9 @@
|
||||
"permissions": [
|
||||
"users",
|
||||
"admins"
|
||||
],
|
||||
"modules": [
|
||||
"spoilers"
|
||||
]
|
||||
},
|
||||
"cancel": {
|
||||
@@ -99,6 +105,7 @@
|
||||
"admins"
|
||||
],
|
||||
"modules": [
|
||||
"spoilers",
|
||||
"applications",
|
||||
"sponsorships"
|
||||
]
|
||||
@@ -107,7 +114,6 @@
|
||||
"permissions": [
|
||||
"users",
|
||||
"admins",
|
||||
"group_users",
|
||||
"group_admins"
|
||||
],
|
||||
"modules": [
|
||||
@@ -116,7 +122,7 @@
|
||||
},
|
||||
"warn": {
|
||||
"permissions": [
|
||||
"group_users"
|
||||
"group_users_admins"
|
||||
],
|
||||
"modules": [
|
||||
"warnings"
|
||||
@@ -142,8 +148,7 @@
|
||||
},
|
||||
"reboot": {
|
||||
"permissions": [
|
||||
"admins",
|
||||
"group_admins"
|
||||
"owner"
|
||||
],
|
||||
"modules": [
|
||||
"general"
|
||||
@@ -194,6 +199,14 @@
|
||||
"modules": [
|
||||
"applications"
|
||||
]
|
||||
},
|
||||
"resetcommands": {
|
||||
"permissions": [
|
||||
"owner"
|
||||
],
|
||||
"modules": [
|
||||
"general"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
from os import getpid, makedirs
|
||||
from time import time
|
||||
from modules.utils import *
|
||||
from modules.inline import *
|
||||
from app import app
|
||||
@@ -19,6 +20,7 @@ from modules.commands.message import *
|
||||
from modules.commands.nearby import *
|
||||
from modules.commands.reapply import *
|
||||
from modules.commands.reboot import *
|
||||
from modules.commands.resetcommands import *
|
||||
from modules.commands.rules import *
|
||||
from modules.commands.spoiler import *
|
||||
from modules.commands.sponsorship import *
|
||||
@@ -37,7 +39,6 @@ from modules.callbacks.sus import *
|
||||
from modules.handlers.confirmation import *
|
||||
from modules.handlers.contact import *
|
||||
from modules.handlers.group_join import *
|
||||
from modules.handlers.sponsorship import *
|
||||
from modules.handlers.voice import *
|
||||
from modules.handlers.welcome import *
|
||||
from modules.handlers.everything import *
|
||||
@@ -53,7 +54,16 @@ if __name__ == "__main__":
|
||||
app.start()
|
||||
|
||||
try:
|
||||
app.send_message(configGet("owner"), f"Starting up with pid `{pid}`")
|
||||
if path.exists(path.join(configGet("cache", "locations"), "shutdown_time")):
|
||||
downtime = relativedelta(datetime.now(), datetime.fromtimestamp(jsonLoad(path.join(configGet("cache", "locations"), "shutdown_time"))["timestamp"]))
|
||||
if downtime.days >= 1:
|
||||
app.send_message(configGet("owner"), locale("startup_downtime_days", "message").format(pid, downtime.days))
|
||||
elif downtime.hours >= 1:
|
||||
app.send_message(configGet("owner"), locale("startup_downtime_hours", "message").format(pid, downtime.hours))
|
||||
else:
|
||||
app.send_message(configGet("owner"), locale("startup_downtime_minutes", "message").format(pid, downtime.minutes))
|
||||
else:
|
||||
app.send_message(configGet("owner"), locale("startup", "message").format(pid))
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
logWrite(f"Could not send startup message to bot owner. Perhaps user has not started the bot yet.")
|
||||
|
||||
@@ -62,10 +72,13 @@ if __name__ == "__main__":
|
||||
idle()
|
||||
|
||||
try:
|
||||
app.send_message(configGet("owner"), f"Shutting with pid `{pid}`")
|
||||
app.send_message(configGet("owner"), locale("shutdown", "message").format(pid))
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
logWrite(f"Could not send shutdown message to bot owner. Perhaps user has not started the bot yet.")
|
||||
|
||||
app.stop()
|
||||
|
||||
makedirs(configGet("cache", "locations"), exist_ok=True)
|
||||
jsonSave({"timestamp": time()}, path.join(configGet("cache", "locations"), "shutdown_time"))
|
||||
|
||||
killProc(pid)
|
@@ -13,6 +13,7 @@
|
||||
"question8": "Чи дивишся ти стріми дівчат Хололайву?",
|
||||
"question9": "Чиї пісні з Хололайву тобі подобаються найбільше?",
|
||||
"question10": "Ну і нарешті, розкажи трохи про себе. Про хобі, чим тобі подобається займатись. Одним повідомленням, будь ласка.",
|
||||
"question_too_long": "Текст занадто довгий. Будь ласка, умісти відповідь у 256 символів.",
|
||||
"question2_underage": "Вибач, але треба досягти віку {0} років, щоб приєднатись до нас. Такі обмеження існують для того, щоб всім у спільноті було цікаво одне з одним.",
|
||||
"question2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
||||
"question2_joke": "Шутнік, ми так і поняли. Але будь ласка, введи реальне значення.",
|
||||
@@ -20,9 +21,11 @@
|
||||
"question3_found": "Використовую наступний результат:\n• {0} ({1})",
|
||||
"question3_error": "⚠️ **Сталась помилка**\nНе вдалось отримати географічну мітку. Розробника повідомлено про цю помилку. Будь ласка, спробуйте ще раз.",
|
||||
"question3_traceback": "⚠️ **Сталась помилка**\nПомилка отримання геокодингу для `{0}`\nПомилка: `{1}`\n\nTraceback:\n```\n{2}\n```",
|
||||
"question10_too_long": "Текст занадто довгий. Будь ласка, умісти відповідь у 1024 символи.",
|
||||
"sponsorship_apply": "ℹ️ Оформіть платну підписку на когось з Холо, заповніть форму та отримайте особливу роль в якості винагороди!",
|
||||
"sponsorship_applying": "ℹ️ Розпочато заповнення форми на отримання бонусів за платну підписку на холодівчат.",
|
||||
"sponsor1": "На яку саме дівчину платна підписка?",
|
||||
"sponsor1_invalid": "Будь ласка, введіть ім'я не довше за 240 символів",
|
||||
"sponsor2": "До якої дати (`ДД.ММ.РРРР`) підписка?",
|
||||
"sponsor2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
||||
"sponsor2_past": "Вказана дата знаходиться в минулому. Будь ласка, вкажіть правильний термін дії підписки",
|
||||
@@ -38,7 +41,9 @@
|
||||
"sponsor_got": "Отримано форму на спонсорство від `{0}`\n\nІм'я тг: `{1}`\nЮзернейм: @{2}\n\n**Дані форми:**\n{3}",
|
||||
"shutdown": "Вимкнення бота з підом `{0}`",
|
||||
"startup": "Запуск бота з підом `{0}`",
|
||||
"startup_downtime": "Запуск бота з підом `{0}` (лежав {1})",
|
||||
"startup_downtime_minutes": "Запуск бота з підом `{0}` (лежав {1} хв.)",
|
||||
"startup_downtime_hours": "Запуск бота з підом `{0}` (лежав {1} год.)",
|
||||
"startup_downtime_days": "Запуск бота з підом `{0}` (лежав {1} дн.)",
|
||||
"approved": "Вітаємо! Твою анкету переглянули та підтвердили твоє право на вступ. Скористайся кнопкою під повідомленням щоб вступити до нашої лампової спільноти!",
|
||||
"approved_joined": "Вітаємо! Твою анкету переглянули та підтвердили її правильність. Дякуємо за витрачений на заповнення час та гарного дня!",
|
||||
"read_rules": "Будь ласка, прочитай ці правила перш ніж натискати на кнопку та приєднуватись до чату.",
|
||||
@@ -90,7 +95,7 @@
|
||||
"sponsorships_expires": "⚠️ **Нагадування**\nНадана платна підписка припинить діяти **за {0} д**. Будь ласка, оновіть дані про неї командою /sponsorship інакше роль буде втрачено!",
|
||||
"sponsorships_expired": "⚠️ **Нагадування**\nТермін дії вказаної підписки сплив. Для повторного отримання ролі користуйся командою /sponsorship.",
|
||||
"label_too_long": "Довжина назви ролі не повинна перевищувати 16 символів",
|
||||
"finish_sponsorship": "❌ **Дія неможлива**\nПерш ніж заповнювати анкету, треба завершити заповнення форми спонсора.",
|
||||
"finish_sponsorship": "❌ **Дія неможлива**\nПерш ніж заповнювати анкету, треба завершити заповнення форми спонсора або перервати його командою /cancel.",
|
||||
"finish_application": "❌ **Дія неможлива**\nПерш ніж заповнювати форму спонсора, треба завершити заповнення анкети.",
|
||||
"nearby_invalid": "ℹ️ **Місце не знайдено**\nЗа наданим запитом не знайдено місце з координатами. Спробуйте ще раз формулючи запит в стилі \"Чернівці\" або \"Київська область\".",
|
||||
"nearby_error": "⚠️ **Сталась помилка**\n\nПомилка: `{0}`\n\nTraceback:\n```\n{1}\n```",
|
||||
@@ -100,15 +105,19 @@
|
||||
"identify_invalid_syntax": "Неправильний синтаксис!\nТреба: `/identify ID/NAME/USERNAME`",
|
||||
"identify_not_found": "Не знайдено користувачів за запитом **{0}**",
|
||||
"identify_success": "Користувач `{0}`\n\nІм'я: {1}\nЮзернейм: {2}\nЄ в чаті: {3}\nЄ адміном: {4}\nРоль: {5}\nНаявна анкета: {6}\nНаявне спонсорство: {7}",
|
||||
"spoiler_started": "Розпочато створення спойлера. Надішліть щось",
|
||||
"spoiler_started": "Розпочато створення спойлера. Будь ласка, оберіть категорію спойлера за допомогою клавіатури бота.",
|
||||
"spoiler_unfinished": "У вас ще є незавершений спойлер. Надішліть /cancel щоб зупинити його створення",
|
||||
"spoiler_cancel": "Створення спойлера було припинено",
|
||||
"spoiler_empty": "Спойлер без опису",
|
||||
"spoiler_described": "Спойлер: {0}",
|
||||
"spoiler_empty": "Спойлер категорії \"{0}\" без опису",
|
||||
"spoiler_described": "Спойлер категорії \"{0}\": {1}",
|
||||
"spoiler_description_enter": "Добре, введіть бажаний опис спойлера",
|
||||
"spoiler_using_description": "Встановлено опис спойлера: {0}",
|
||||
"spoiler_send_description": "Майже впорались. Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.",
|
||||
"spoiler_description_too_long": "Текст занадто довгий. Будь ласка, умісти опис у 1024 символи.",
|
||||
"spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)",
|
||||
"spoiler_send_description": "Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.",
|
||||
"spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.",
|
||||
"spoiler_incorrect_content": "Бот не підтримує такий контент. Будь ласка, надішли текст, фото, відео, файл або анімацію (гіф).",
|
||||
"spoiler_incorrect_category": "Вказана категорія не є дійсною. Будь ласка, користуйся клавіатурою бота (кнопка біля 📎) для вибору категорії.",
|
||||
"spoiler_in_progress": "❌ **Дія неможлива**\nПерш ніж починати нову дію, треба завершити створення спойлера або перервати його командою /cancel.",
|
||||
"yes": "Так",
|
||||
"no": "Ні",
|
||||
"voice_message": [
|
||||
@@ -132,6 +141,11 @@
|
||||
"question_streamer": "Стрімер:",
|
||||
"question_expires": "Підписка до:",
|
||||
"question_label": "Хоче роль:"
|
||||
},
|
||||
"spoiler_categories": {
|
||||
"nsfw": "NSFW контент",
|
||||
"deanon": "Деанон холо-учасників",
|
||||
"other": "Інше"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
@@ -156,7 +170,7 @@
|
||||
"Ні, повторно заповнити"
|
||||
]
|
||||
],
|
||||
"spoiler_description": [
|
||||
"spoiler_categories": [
|
||||
[
|
||||
"NSFW контент"
|
||||
],
|
||||
@@ -164,7 +178,7 @@
|
||||
"Деанон холо-учасників"
|
||||
],
|
||||
[
|
||||
"Інше (надішліть свій текст)"
|
||||
"Інше"
|
||||
]
|
||||
]
|
||||
},
|
||||
@@ -252,7 +266,7 @@
|
||||
"description": "Надіслати цей спойлер до чату"
|
||||
}
|
||||
},
|
||||
"rules_msg": "📢Правила можуть доповнюватись та змінюватись, залежно від потреби. У такому разі, порушення, які були вчинені до введення (змінення) правила, порушеннями вважатися не будуть. Про всі зміни в правилах, ви будете проінформовані за допомогою закріплених повідомлень. Але вони не будуть закріплені на постійній основі, тому, час від часу, перевіряйте актуальність правил у боті.\n\n🔔Якщо ви бачите, як хтось із учасників порушив правила, тегніть одного із адмінів, у відповідь на повідомлення, яке, на вашу думку, є порушенням. У дописі до тегу, вкажіть, по якому пункту ви побачили порушення. Або перешліть повідомлення до будь кого із адміністраторів у особисті повідомлення, та коротко опишіть ситуацію.\nСписок адміністраторів: @Chirkopol @Za_NerZula @Denialvapr\nЗ питань функціонування бота звертайтесь до @Profitroll2281337\n\n❗️Будь-який заборонений контент, може бути відправлений до чату за допомогою бота - https://t.me/spoilerobot з повним описом контенту, що міститься під спойлером. За неправильний або некоректний опис, може бути видане попередження.\n\n‼️Видалені або змінені повідомлення, все ще є повідомленнями від вашого імені, які могли побачити учасники чату, і які можуть бути відстежені через адмінську панель.\n\n🔨 За порушення - ви отримаєте попередження. За наявності 3-х попереджень - мут на добу. За повторні порушення, ви одразу отримаєте покарання, без додаткових попереджень.",
|
||||
"rules_msg": "📢Правила можуть доповнюватись та змінюватись, залежно від потреби. У такому разі, порушення, які були вчинені до введення (змінення) правила, порушеннями вважатися не будуть. Про всі зміни в правилах, ви будете проінформовані за допомогою закріплених повідомлень. Але вони не будуть закріплені на постійній основі, тому, час від часу, перевіряйте актуальність правил у боті.\n\n🔔Якщо ви бачите, як хтось із учасників порушив правила, тегніть одного із адмінів, у відповідь на повідомлення, яке, на вашу думку, є порушенням. У дописі до тегу, вкажіть, по якому пункту ви побачили порушення. Або перешліть повідомлення до будь кого із адміністраторів у особисті повідомлення, та коротко опишіть ситуацію.\nСписок адміністраторів: @Chirkopol @Za_NerZula @Denialvapr\nЗ питань функціонування бота звертайтесь до @Profitroll2281337\n\n❗️Будь-який заборонений контент, може бути відправлений допомогою команди /spoiler у бота - з повним описом контенту, що міститься під спойлером. За неправильний або некоректний опис, може бути видане попередження.\n\n‼️Видалені або змінені повідомлення, все ще є повідомленнями від вашого імені, які могли побачити учасники чату, і які можуть бути відстежені через адмінську панель.\n\n🔨 За порушення - ви отримаєте попередження. За наявності 3-х попереджень - мут на добу. За повторні порушення, ви одразу отримаєте покарання, без додаткових попереджень.",
|
||||
"rules": [
|
||||
"1️⃣) \"HoloKyiv Chat\" та \"HoloUA (Hololive Ukraine) Chat\" створені виключно для українців (13+). В них можуть знаходитись тільки люди які: \n- Народились в Україні, та проживають, на данний момент, у ній.\n- Народились за межами України, але проживають у ній.\n- Народились в Україні але, на даний момент, не проживають у ній.\n\"HoloUA (Hololive Ukraine) Chat\" відкритий для усіх українців. Щоб потрапити до нього, заповніть, будь ласка, анкету, та дочекайтесь, поки її схвалять адміни.\nУ \"HoloKyiv Chat\" можна потрапити тільки особисто, якщо ви проживаєте у Київі, або є близьким другом одного із учасників чату. Із приводу додавання до чату пишіть @Chirkopol у приватні повідомлення.\n🔨 Якщо у процесі спілкування виявиться, що ви не українець, вас буде видалено із чату, до моменту, поки ви їм не станете. Без образ. Ми створюємо виключно українське ком'юніті.",
|
||||
"2️⃣) Заборонено поширення NSFW-контенту з прямим або частково прихованим порнографічним змістом. На контенті \"еротичного характеру\" повинні бути закриті \"сумнівні\" ділянки тіл. \nЗаборонено поширення шок-контенту з великою наявністю крові та/або фізичних пошкоджень.",
|
||||
@@ -275,6 +289,7 @@
|
||||
"nearby": "Показати користувачів поблизу",
|
||||
"reapply": "Повторно заповнити анкету",
|
||||
"reboot": "Перезапустити бота",
|
||||
"resetcommands": "Відреєструвати всі команди",
|
||||
"rules": "Правила спільноти",
|
||||
"spoiler": "Почати створювати спойлер",
|
||||
"sponsorship": "Отримати роль за спонсорство",
|
||||
|
@@ -21,8 +21,15 @@ async def callback_reapply_query_accept(app: Client, clb: CallbackQuery):
|
||||
|
||||
await app.send_message(holo_user.id, locale("approved_joined", "message", locale=holo_user))
|
||||
|
||||
col_applications.delete_one({"user": holo_user.id})
|
||||
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
||||
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"]})
|
||||
elif applications == 1:
|
||||
col_applications.find_one_and_replace({"user": holo_user.id}, {"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
||||
else:
|
||||
col_applications.insert_one({"user": holo_user.id, "date": datetime.now(), "admin": clb.from_user.id, "application": col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "application"}})["application"]})
|
||||
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"state": "approved", "sent": False}})
|
||||
|
||||
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
||||
|
@@ -3,6 +3,7 @@ from app import app
|
||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ForceReply, CallbackQuery
|
||||
from pyrogram.client import Client
|
||||
from pyrogram import filters
|
||||
from classes.errors.holo_user import LabelSettingError
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.utils import configGet, locale, logWrite, should_quote
|
||||
from modules.database import col_tmp, col_sponsorships
|
||||
@@ -67,7 +68,10 @@ async def callback_query_sponsor_yes(app: Client, clb: CallbackQuery):
|
||||
}
|
||||
)
|
||||
|
||||
await holo_user.label_set(configGet("users", "groups"), col_tmp.find_one({"user": {"$eq": holo_user.id}, "type": {"$eq": "sponsorship"}})["sponsorship"]["label"])
|
||||
try:
|
||||
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)
|
||||
|
||||
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
||||
|
||||
|
@@ -5,13 +5,14 @@ from pyrogram.enums.parse_mode import ParseMode
|
||||
from pyrogram.types import Message
|
||||
from pyrogram.errors import bad_request_400
|
||||
from pyrogram.client import Client
|
||||
from classes.holo_user import HoloUser, UserNotFoundError
|
||||
from classes.errors.holo_user import UserNotFoundError
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.utils import logWrite, locale, should_quote
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from modules.database import col_applications
|
||||
from modules import custom_filters
|
||||
|
||||
# Applications command =========================================================================================================
|
||||
# Application command ==========================================================================================================
|
||||
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.command(["application"], prefixes=["/"]) & custom_filters.admin)
|
||||
async def cmd_application(app: Client, msg: Message):
|
||||
|
||||
@@ -55,42 +56,6 @@ async def cmd_application(app: Client, msg: Message):
|
||||
|
||||
logWrite(f"User {msg.from_user.id} requested application of {holo_user.id}")
|
||||
await msg.reply_text(locale("contact", "message", locale=msg.from_user).format(holo_user.id, "\n".join(application_content), application_status), parse_mode=ParseMode.MARKDOWN, quote=should_quote(msg))
|
||||
|
||||
# if (path.exists(f"{configGet('data', 'locations')}{sep}users{sep}{msg.command[1]}.json") and jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{msg.command[1]}.json")["approved"]):
|
||||
# user_id = int(msg.command[1])
|
||||
# else:
|
||||
# list_of_users = []
|
||||
# async for m in app.get_chat_members(configGet("users", "groups"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]):
|
||||
# list_of_users.append(m)
|
||||
# user_id = list_of_users[0].user.id
|
||||
# try:
|
||||
# user_data = jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{user_id}.json")
|
||||
# application = jsonLoad(f"{configGet('data', 'locations')}{sep}applications.json")[str(user_id)]
|
||||
# application_content = []
|
||||
# i = 1
|
||||
# for question in configGet("application", file=str(msg.from_user.id)):
|
||||
# if i == 2:
|
||||
# age = relativedelta(datetime.now(), datetime.strptime(application['application']['2'], '%d.%m.%Y'))
|
||||
# application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {application['application']['2']} ({age.years} р.)")
|
||||
# else:
|
||||
# application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {application['application'][question]}")
|
||||
# i += 1
|
||||
# if user_data["sent"]:
|
||||
# if user_data["approved"]:
|
||||
# application_status = locale("application_status_accepted", "message").format((await app.get_users(application["approved_by"])).first_name, datetime.fromtimestamp(application["approval_date"]).strftime("%d.%m.%Y, %H:%M"))
|
||||
# elif application["rejected"]:
|
||||
# application_status = locale("application_status_rejected", "message").format((await app.get_users(application["rejected_by"])).first_name, datetime.fromtimestamp(application["refusal_date"]).strftime("%d.%m.%Y, %H:%M"))
|
||||
# else:
|
||||
# application_status = locale("application_status_on_hold", "message")
|
||||
# else:
|
||||
# if user_data["approved"]:
|
||||
# application_status = locale("application_status_accepted", "message").format((await app.get_users(application["approved_by"])).first_name, datetime.fromtimestamp(application["approval_date"]).strftime("%d.%m.%Y, %H:%M"))
|
||||
# elif application["rejected"]:
|
||||
# application_status = locale("application_status_rejected", "message").format((await app.get_users(application["rejected_by"])).first_name, datetime.fromtimestamp(application["refusal_date"]).strftime("%d.%m.%Y, %H:%M"))
|
||||
# else:
|
||||
# application_status = locale("application_status_not_send", "message")
|
||||
# logWrite(f"User {msg.from_user.id} requested application of {user_id}")
|
||||
# await msg.reply_text(locale("contact", "message").format(str(user_id), "\n".join(application_content), application_status), quote=should_quote(msg))
|
||||
|
||||
except IndexError:
|
||||
await msg.reply_text(locale("application_invalid_syntax", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||
|
@@ -1,14 +1,16 @@
|
||||
from app import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message
|
||||
from pyrogram.types import Message, ReplyKeyboardRemove
|
||||
from pyrogram.client import Client
|
||||
from modules.utils import should_quote, logWrite, locale
|
||||
from modules.database import col_tmp, col_spoilers
|
||||
from modules import custom_filters
|
||||
|
||||
# Cancel command ===============================================================================================================
|
||||
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("cancel", prefixes=["/"]))
|
||||
async def command_cancel(app: Client, msg: Message):
|
||||
col_tmp.delete_many( {"user": msg.from_user.id} )
|
||||
col_tmp.delete_many( {"user": msg.from_user.id, "sent": False} )
|
||||
col_spoilers.delete_many( {"user": msg.from_user.id, "completed": False} )
|
||||
await msg.reply_text(locale("cancel", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||
logWrite(f"Cancelling all ongoing tmp operations for {msg.from_user.id}")
|
||||
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}")
|
||||
# ==============================================================================================================================
|
@@ -5,12 +5,14 @@ from pyrogram.types import Message
|
||||
from pyrogram.client import Client
|
||||
from pyrogram.errors import bad_request_400
|
||||
from pyrogram.enums.chat_action import ChatAction
|
||||
from classes.holo_user import HoloUser, UserNotFoundError, UserInvalidError
|
||||
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 import custom_filters
|
||||
|
||||
# Identify command =============================================================================================================
|
||||
@app.on_message((custom_filters.enabled_applications | custom_filters.enabled_sponsorships) & ~filters.scheduled & filters.command("identify", prefixes=["/"]) & custom_filters.admin)
|
||||
async def command_identify(app: Client, msg: Message):
|
||||
async def cmd_identify(app: Client, msg: Message):
|
||||
|
||||
if len(msg.command) != 2:
|
||||
await msg.reply_text(locale("identify_invalid_syntax", "message", locale=msg.from_user))
|
||||
@@ -60,4 +62,5 @@ async def command_identify(app: Client, msg: Message):
|
||||
quote=should_quote(msg)
|
||||
)
|
||||
|
||||
logWrite(f"User {msg.from_user.id} identified user {holo_user.id}")
|
||||
logWrite(f"User {msg.from_user.id} identified user {holo_user.id}")
|
||||
# ==============================================================================================================================
|
@@ -2,10 +2,12 @@ from app import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message
|
||||
from pyrogram.client import Client
|
||||
from modules.utils import locale, should_quote, find_user
|
||||
from classes.holo_user import HoloUser, LabelTooLongError
|
||||
from modules.utils import configGet, locale, should_quote, find_user
|
||||
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):
|
||||
|
||||
@@ -31,7 +33,11 @@ async def cmd_label(app: Client, msg: Message):
|
||||
except LabelTooLongError:
|
||||
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)
|
||||
return
|
||||
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")
|
||||
await msg.reply_text(f"User not found")
|
||||
# ==============================================================================================================================
|
@@ -2,8 +2,9 @@ from app import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message
|
||||
from pyrogram.client import Client
|
||||
from classes.errors.holo_user import UserInvalidError
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.utils import logWrite, locale, should_quote
|
||||
from modules.utils import logWrite, locale, should_quote, find_user
|
||||
from modules import custom_filters
|
||||
|
||||
# Message command ==============================================================================================================
|
||||
@@ -14,15 +15,15 @@ async def cmd_message(app: Client, msg: Message):
|
||||
|
||||
try:
|
||||
destination = HoloUser(int(msg.command[1]))
|
||||
except ValueError:
|
||||
destination = HoloUser(msg.command[1])
|
||||
except (ValueError, UserInvalidError):
|
||||
destination = HoloUser(await find_user(app, query=msg.command[1]))
|
||||
|
||||
if ((msg.text is not None) and (len(msg.text.split()) > 2)):
|
||||
await destination.message(context=msg, text=" ".join(msg.text.split()[2:]), caption=msg.caption, photo=msg.photo, video=msg.video, file=msg.document, adm_context=True)
|
||||
await destination.message(context=msg, text=" ".join(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=msg.text, caption=" ".join(msg.caption.split()[2:]), photo=msg.photo, video=msg.video, file=msg.document, adm_context=True)
|
||||
await destination.message(context=msg, text=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, 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))
|
||||
|
@@ -38,7 +38,6 @@ async def cmd_nearby(app: Client, msg: Message):
|
||||
# Find all users registered in the area provided
|
||||
output = []
|
||||
applications_nearby = col_applications.find( {"application.3.location": { "$nearSphere": {"$geometry": {"type": "Point", "coordinates": [location[0], location[1]]}, "$maxDistance": configGet("search_radius")*1000} } } )
|
||||
# {"application": {"3": {"location": {"$near": { "$geometry": { "type": "Point", "coordinates": location }, "$maxDistance": 30000 }} } } } )
|
||||
|
||||
for entry in applications_nearby:
|
||||
if not entry["user"] == msg.from_user.id:
|
||||
@@ -56,18 +55,4 @@ async def cmd_nearby(app: Client, msg: Message):
|
||||
await msg.reply_text(locale("nearby_result", "message", locale=holo_user).format("\n".join(output)), quote=should_quote(msg))
|
||||
else:
|
||||
await msg.reply_text(locale("nearby_empty", "message", locale=holo_user), quote=should_quote(msg))
|
||||
|
||||
# if not path.exists(f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json"):
|
||||
# jsonSave(jsonLoad(f"{configGet('data', 'locations')}{sep}sponsor_default.json"), f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json")
|
||||
# sponsor = jsonLoad(f"{configGet('data', 'locations')}{sep}sponsors{sep}{msg.from_user.id}.json")
|
||||
# if sponsor["approved"]:
|
||||
# if sponsor["expires"] is not None:
|
||||
# if datetime.strptime(sponsor["expires"], "%d.%m.%Y") > datetime.now():
|
||||
# await msg.reply_text(f"You have an active sub til **{sponsor['expires']}**.")
|
||||
# else:
|
||||
# await msg.reply_text(f"Your sub expired {int((datetime.now()-datetime.strptime(sponsor['expires'], '%d.%m.%Y')).days)} days ago.")
|
||||
# elif sponsor["approved"]:
|
||||
# await msg.reply_text(f"Your sub expiration date is not valid.")
|
||||
# else:
|
||||
# await msg.reply_text(f"You have no active subscription.")
|
||||
# ==============================================================================================================================
|
@@ -3,6 +3,7 @@ from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
|
||||
from pyrogram.client import Client
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.logging import logWrite
|
||||
from modules.utils import configGet, locale, should_quote
|
||||
from modules.handlers.welcome import welcome_pass
|
||||
from modules.database import col_tmp
|
||||
@@ -15,7 +16,7 @@ async def cmd_reapply(app: Client, msg: Message):
|
||||
holo_user = HoloUser(msg.from_user)
|
||||
|
||||
# Check if user has approved/rejected tmp application
|
||||
if (holo_user.application_state()[0] in ["approved", "rejected"]) or (holo_user.application_state()[0] == "none"):
|
||||
if ((holo_user.application_state()[0] in ["approved", "rejected"]) or (holo_user.application_state()[0] == "none")) and holo_user.spoiler_state() is False:
|
||||
|
||||
# Check if user's tmp application is already completed or even sent
|
||||
if ((holo_user.application_state()[1] is True) and (not col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"])) or (holo_user.application_state()[0] == "none"):
|
||||
@@ -34,14 +35,22 @@ async def cmd_reapply(app: Client, msg: Message):
|
||||
await welcome_pass(app, msg, once_again=True)
|
||||
|
||||
else:
|
||||
await msg.reply_text(locale("reapply_left_chat", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup([
|
||||
[
|
||||
InlineKeyboardButton(locale("reapply_old_one", "button", locale=holo_user), f"reapply_old_{msg.id}")
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(locale("reapply_new_one", "button", locale=holo_user), f"reapply_new_{msg.id}")
|
||||
]
|
||||
]))
|
||||
|
||||
if holo_user.application_state()[1] is True and holo_user.application_state()[0] != "fill":
|
||||
|
||||
await msg.reply_text(locale("reapply_left_chat", "message", locale=holo_user), reply_markup=InlineKeyboardMarkup([
|
||||
[
|
||||
InlineKeyboardButton(locale("reapply_old_one", "button", locale=holo_user), f"reapply_old_{msg.id}")
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(locale("reapply_new_one", "button", locale=holo_user), f"reapply_new_{msg.id}")
|
||||
]
|
||||
]))
|
||||
|
||||
else:
|
||||
|
||||
holo_user.application_restart(reapply=True)
|
||||
await welcome_pass(app, msg, once_again=True)
|
||||
|
||||
else:
|
||||
|
||||
@@ -51,6 +60,10 @@ async def cmd_reapply(app: Client, msg: Message):
|
||||
]
|
||||
]))
|
||||
|
||||
elif holo_user.spoiler_state() is True:
|
||||
|
||||
await msg.reply_text(locale("spoiler_in_progress", "message", locale=holo_user))
|
||||
|
||||
else:
|
||||
|
||||
if (holo_user.application_state()[0] == "fill") and (col_tmp.find_one({"user": holo_user.id, "type": "application"})["sent"] is True):
|
||||
|
@@ -1,21 +1,24 @@
|
||||
from app import app
|
||||
from os import getpid
|
||||
from os import getpid, makedirs, path
|
||||
from sys import exit
|
||||
from time import time
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message
|
||||
from pyrogram.client import Client
|
||||
from modules.utils import locale, logWrite, should_quote
|
||||
from modules.utils import configGet, jsonSave, locale, logWrite, should_quote
|
||||
from modules.scheduled import scheduler
|
||||
from modules import custom_filters
|
||||
|
||||
pid = getpid()
|
||||
|
||||
# Shutdown command =============================================================================================================
|
||||
# Reboot command ===============================================================================================================
|
||||
@app.on_message(custom_filters.enabled_general & ~filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["/"]) & custom_filters.admin)
|
||||
async def cmd_kill(app: Client, msg: Message):
|
||||
|
||||
logWrite(f"Shutting down bot with pid {pid}")
|
||||
await msg.reply_text(locale("shutdown", "message", locale=msg.from_user).format(pid), quote=should_quote(msg))
|
||||
scheduler.shutdown()
|
||||
makedirs(configGet("cache", "locations"), exist_ok=True)
|
||||
jsonSave({"timestamp": time()}, path.join(configGet("cache", "locations"), "shutdown_time"))
|
||||
exit()
|
||||
# ==============================================================================================================================
|
58
modules/commands/resetcommands.py
Normal file
58
modules/commands/resetcommands.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from app import app
|
||||
from os import getpid, listdir
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message, BotCommandScopeDefault, BotCommandScopeChat
|
||||
from pyrogram.errors import bad_request_400
|
||||
from pyrogram.client import Client
|
||||
from modules.utils import logWrite, should_quote, configGet
|
||||
from modules import custom_filters
|
||||
|
||||
pid = getpid()
|
||||
|
||||
# Reset commands command =======================================================================================================
|
||||
@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 = []
|
||||
files_locales = listdir(f'{configGet("locale", "locations")}')
|
||||
|
||||
for entry in files_locales:
|
||||
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")))
|
||||
|
||||
for admin in configGet("admins"):
|
||||
try:
|
||||
logWrite(f'Resetting commands for admin {admin}', debug=True)
|
||||
await app.delete_bot_commands(scope=BotCommandScopeChat(chat_id=admin))
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
pass
|
||||
|
||||
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")))
|
||||
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 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)
|
||||
# ==============================================================================================================================
|
@@ -1,8 +1,10 @@
|
||||
from app import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message, ForceReply
|
||||
from pyrogram.types import Message, ReplyKeyboardMarkup
|
||||
from pyrogram.client import Client
|
||||
from classes.holo_user import HoloUser, UserInvalidError, UserNotFoundError
|
||||
from classes.errors.holo_user import UserNotFoundError, UserInvalidError
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.logging import logWrite
|
||||
from modules.utils import locale
|
||||
from modules.database import col_spoilers
|
||||
from modules import custom_filters
|
||||
@@ -24,15 +26,20 @@ async def cmd_spoiler(app: Client, msg: Message):
|
||||
{
|
||||
"user": msg.from_user.id,
|
||||
"completed": False,
|
||||
"category": None,
|
||||
"description": None,
|
||||
"photo": None,
|
||||
"video": None,
|
||||
"audio": None,
|
||||
"animation": None,
|
||||
"document": None,
|
||||
"caption": None,
|
||||
"text": None
|
||||
}
|
||||
)
|
||||
|
||||
await msg.reply_text(locale("spoiler_started", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_content", "force_reply", locale=msg.from_user)))
|
||||
await msg.reply_text(locale("spoiler_started", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_categories", "keyboard"), resize_keyboard=True, one_time_keyboard=True))
|
||||
logWrite(f"User {msg.from_user.id} started creating new spoiler")
|
||||
|
||||
else:
|
||||
await msg.reply_text(locale("spoiler_unfinished", "message", locale=msg.from_user))
|
||||
|
@@ -10,9 +10,13 @@ from modules.database import col_applications
|
||||
# Sponsorship command ==========================================================================================================
|
||||
@app.on_message(custom_filters.enabled_sponsorships & ~filters.scheduled & filters.command(["sponsorship"], prefixes=["/"]) & (custom_filters.allowed | custom_filters.admin))
|
||||
async def cmd_sponsorship(app: Client, msg: Message):
|
||||
if HoloUser(msg.from_user).application_state()[0] == "fill":
|
||||
holo_user = HoloUser(msg.from_user)
|
||||
if holo_user.application_state()[0] == "fill":
|
||||
await msg.reply_text(locale("finish_application", "message", locale=msg.from_user), quote=should_quote(msg))
|
||||
return
|
||||
if holo_user.spoiler_state() is True:
|
||||
await msg.reply_text(locale("spoiler_in_progress", "message", locale=holo_user))
|
||||
return
|
||||
await msg.reply_text(locale("sponsorship_apply", "message", locale=msg.from_user), reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(text=str(locale("sponsor_apply", "button", locale=msg.from_user)), callback_data=f"sponsor_apply_{msg.from_user.id}")]]), quote=should_quote(msg))
|
||||
# else:
|
||||
# await msg.reply_text(locale("sponsorship_application_empty", "message"))
|
||||
|
@@ -33,11 +33,15 @@ async def cmd_start(app: Client, msg: Message):
|
||||
try:
|
||||
spoiler = col_spoilers.find_one( {"_id": ObjectId(msg.command[1])} )
|
||||
if spoiler["photo"] is not None:
|
||||
await msg.reply_photo(spoiler["photo"])
|
||||
await msg.reply_cached_media(spoiler["photo"], caption=spoiler["caption"])
|
||||
if spoiler["video"] is not None:
|
||||
await msg.reply_video(spoiler["video"])
|
||||
await msg.reply_cached_media(spoiler["video"], caption=spoiler["caption"])
|
||||
if spoiler["audio"] is not None:
|
||||
await msg.reply_cached_media(spoiler["audio"], caption=spoiler["caption"])
|
||||
if spoiler["animation"] is not None:
|
||||
await msg.reply_animation(spoiler["animation"])
|
||||
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"])
|
||||
if spoiler["text"] is not None:
|
||||
await msg.reply_text(spoiler["text"])
|
||||
except InvalidId:
|
||||
|
@@ -4,7 +4,7 @@ usage in context of Holo Users."""
|
||||
from os import path
|
||||
from app import isAnAdmin
|
||||
from modules.utils import configGet, jsonLoad
|
||||
from modules.database import col_applications
|
||||
from modules.database import col_applications, col_tmp
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message
|
||||
|
||||
@@ -15,7 +15,11 @@ async def member_func(_, __, msg: Message):
|
||||
return True if (msg.from_user.id in jsonLoad(path.join(configGet("cache", "locations"), "group_members"))) else False
|
||||
|
||||
async def allowed_func(_, __, msg: Message):
|
||||
return True if (col_applications.find_one({"user": msg.from_user.id}) is not None) else False
|
||||
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 = False
|
||||
return output
|
||||
|
||||
async def enabled_general_func(_, __, msg: Message):
|
||||
return configGet("enabled", "features", "general")
|
||||
@@ -35,6 +39,9 @@ async def enabled_invites_check_func(_, __, msg: Message):
|
||||
async def enabled_dinovoice_func(_, __, msg: Message):
|
||||
return configGet("enabled", "features", "dinovoice")
|
||||
|
||||
async def filling_sponsorship_func(_, __, msg: Message):
|
||||
return True if col_tmp.find_one({"user": msg.from_user.id, "type": "sponsorship"}) is not None else False
|
||||
|
||||
admin = filters.create(admin_func)
|
||||
member = filters.create(member_func)
|
||||
allowed = filters.create(allowed_func)
|
||||
@@ -44,4 +51,6 @@ enabled_applications = filters.create(enabled_applications_func)
|
||||
enabled_sponsorships = filters.create(enabled_sponsorships_func)
|
||||
enabled_warnings = filters.create(enabled_warnings_func)
|
||||
enabled_invites_check = filters.create(enabled_invites_check_func)
|
||||
enabled_dinovoice = filters.create(enabled_dinovoice_func)
|
||||
enabled_dinovoice = filters.create(enabled_dinovoice_func)
|
||||
|
||||
filling_sponsorship = filters.create(filling_sponsorship_func)
|
@@ -1,6 +1,4 @@
|
||||
from os import remove, sep
|
||||
from typing import Literal
|
||||
from uuid import uuid1
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from datetime import datetime
|
||||
from app import app
|
||||
@@ -11,7 +9,7 @@ from pyrogram.enums.parse_mode import ParseMode
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.utils import all_locales, configGet, locale, logWrite
|
||||
from modules.handlers.welcome import welcome_pass
|
||||
from modules.database import col_tmp
|
||||
from modules.database import col_tmp, col_applications
|
||||
from modules import custom_filters
|
||||
|
||||
# Confirmation =================================================================================================================
|
||||
@@ -56,8 +54,12 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
|
||||
|
||||
i += 1
|
||||
|
||||
if tmp_application["reapply"]:
|
||||
await app.send_message(chat_id=configGet("admin", "groups"), text=(locale("reapply_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
|
||||
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)),
|
||||
parse_mode=ParseMode.MARKDOWN,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(text=str(locale("reapply_yes", "button")), callback_data=f"reapply_yes_{holo_user.id}")
|
||||
@@ -69,7 +71,11 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
|
||||
)
|
||||
)
|
||||
else:
|
||||
await app.send_message(chat_id=configGet("admin", "groups"), text=(locale("application_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
|
||||
await app.send_message(
|
||||
chat_id=configGet("admin", "groups"),
|
||||
text=(locale("application_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(application_content)),
|
||||
parse_mode=ParseMode.MARKDOWN,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[
|
||||
[
|
||||
InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}")
|
||||
@@ -93,9 +99,6 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
|
||||
|
||||
return
|
||||
|
||||
# configSet(["sent"], True, file=str(holo_user.id))
|
||||
# configSet(["confirmed"], True, file=str(holo_user.id))
|
||||
|
||||
if configGet("enabled", "features", "sponsorships") is True:
|
||||
|
||||
if (kind == "sponsorship") or ((holo_user.sponsorship_state()[0] == "fill") and (holo_user.sponsorship_state()[1] is True)):
|
||||
@@ -118,13 +121,11 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
|
||||
if question == "expires":
|
||||
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question].strftime('%d.%m.%Y')}")
|
||||
elif question == "proof":
|
||||
filename = uuid1()
|
||||
with open(f"tmp{sep}{filename}.jpg", "wb") as f:
|
||||
f.write(tmp_sponsorship['sponsorship']['proof'])
|
||||
continue
|
||||
else:
|
||||
sponsorship_content.append(f"{locale(f'question_{question}', 'message', 'sponsor_titles')} {tmp_sponsorship['sponsorship'][question]}")
|
||||
|
||||
await app.send_photo(chat_id=configGet("admin", "groups"), photo=f"tmp{sep}{filename}.jpg", caption=(locale("sponsor_got", "message")).format(str(holo_user.id), msg.from_user.first_name, msg.from_user.username, "\n".join(sponsorship_content)), parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup(
|
||||
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}")
|
||||
@@ -136,7 +137,7 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
|
||||
)
|
||||
)
|
||||
|
||||
remove(f"tmp{sep}{filename}.jpg")
|
||||
# remove(f"tmp{sep}{filename}.jpg")
|
||||
|
||||
logWrite(f"User {holo_user.id} sent his sponsorship application and it will now be reviewed")
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
from traceback import print_exc
|
||||
from app import app, isAnAdmin
|
||||
import asyncio
|
||||
from ftfy import fix_text
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from pyrogram.types import Message, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from pyrogram.client import Client
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.utils import configGet, logWrite, locale, all_locales
|
||||
@@ -42,13 +44,12 @@ async def any_stage(app: Client, msg: Message):
|
||||
photo=msg.photo,
|
||||
video=msg.video,
|
||||
file=msg.document,
|
||||
animation=msg.animation,
|
||||
voice=msg.voice,
|
||||
adm_origin=await isAnAdmin(context_message.from_user.id),
|
||||
adm_context=await isAnAdmin(msg.from_user.id)
|
||||
)
|
||||
|
||||
# await msg.reply_text(locale("message_sent", "message"), quote=should_quote(msg))
|
||||
# col_messages.insert_one({"origin": {"chat": msg.chat.id, "id": msg.id}, "destination": {"chat": new_message.chat.id, "id": new_message.id}})
|
||||
|
||||
return
|
||||
|
||||
if msg.text is not None:
|
||||
@@ -57,7 +58,11 @@ async def any_stage(app: Client, msg: Message):
|
||||
await holo_user.application_next(msg.text, msg=msg)
|
||||
|
||||
if configGet("enabled", "features", "sponsorships") is True:
|
||||
await holo_user.sponsorship_next(msg.text, msg=msg)
|
||||
|
||||
await holo_user.sponsorship_next(msg.text, msg)
|
||||
|
||||
if msg.photo is not None:
|
||||
await holo_user.sponsorship_next(msg.text, msg=msg, photo=msg.photo)
|
||||
|
||||
if holo_user.application_state()[0] != "fill" and holo_user.sponsorship_state()[0] != "fill":
|
||||
|
||||
@@ -66,94 +71,98 @@ async def any_stage(app: Client, msg: Message):
|
||||
if spoiler is None:
|
||||
return
|
||||
|
||||
if msg.photo is not None:
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"photo": msg.photo.file_id}} )
|
||||
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||
return
|
||||
elif msg.video is not None:
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"video": msg.video.file_id}} )
|
||||
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||
return
|
||||
elif msg.animation is not None:
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"animation": msg.animation.file_id}} )
|
||||
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||
if spoiler["category"] is None:
|
||||
|
||||
found = False
|
||||
|
||||
# Find category in all locales
|
||||
for lc in all_locales("spoiler_categories", "message"):
|
||||
for key in lc:
|
||||
if lc[key] == msg.text:
|
||||
found = True
|
||||
category = key
|
||||
|
||||
if found is False:
|
||||
await msg.reply_text(locale("spoiler_incorrect_category", "message", locale=msg.from_user))
|
||||
return
|
||||
|
||||
col_spoilers.find_one_and_update( {"_id": spoiler["_id"]}, {"$set": {"category": category}} )
|
||||
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||
return
|
||||
|
||||
if spoiler["photo"] is None and spoiler["video"] is None and spoiler["animation"] is None and spoiler["text"] is None:
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"text": msg.text}} )
|
||||
await msg.reply_text(locale("spoiler_send_description", "message", locale=msg.from_user), reply_markup=ReplyKeyboardMarkup(locale("spoiler_description", "keyboard"), resize_keyboard=True, one_time_keyboard=True, placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||
else:
|
||||
for lc in all_locales("spoiler_description", "keyboard"):
|
||||
if msg.text == lc[-1][0]:
|
||||
await msg.reply_text(locale("spoiler_description_enter", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||
return
|
||||
if 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 msg.text != "-":
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text, "completed": True}} )
|
||||
await msg.reply_text(locale("spoiler_using_description", "message", locale=msg.from_user).format(msg.text), reply_markup=ReplyKeyboardRemove())
|
||||
await msg.reply_text(locale("spoiler_ready", "message", locale=msg.from_user), quote=False, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_send", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")]]))
|
||||
msg.text = fix_text(msg.text)
|
||||
if len(msg.text) > 1024:
|
||||
await msg.reply_text(locale("spoiler_description_too_long", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("spoiler_description", "force_reply", locale=msg.from_user)))
|
||||
return
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text}} )
|
||||
else:
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": ""}} )
|
||||
|
||||
# user_stage = configGet("stage", file=str(msg.from_user.id))
|
||||
|
||||
# if user_stage == 1:
|
||||
# await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
# logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
# configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
logWrite(f"Adding description '{msg.text}' to {msg.from_user.id}'s spoiler")
|
||||
await msg.reply_text(locale("spoiler_using_description", "message", locale=msg.from_user).format(msg.text), reply_markup=ForceReply(placeholder=locale("spoiler_content", "force_reply", locale=msg.from_user)))
|
||||
|
||||
# elif user_stage == 2:
|
||||
return
|
||||
|
||||
# try:
|
||||
ready = False
|
||||
|
||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
if msg.photo is not None:
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"photo": msg.photo.file_id, "caption": msg.caption, "completed": True}} )
|
||||
logWrite(f"Adding photo with id {msg.photo.file_id} to {msg.from_user.id}'s spoiler")
|
||||
ready = True
|
||||
|
||||
# input_dt = datetime.strptime(msg.text, "%d.%m.%Y")
|
||||
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")
|
||||
ready = True
|
||||
|
||||
# if datetime.now() <= input_dt:
|
||||
# logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to joking")
|
||||
# await msg.reply_text(locale("question2_joke", "message"), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
||||
if msg.audio is not None:
|
||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"audio": msg.audio.file_id, "caption": msg.caption, "completed": True}} )
|
||||
logWrite(f"Adding video with id {msg.audio.file_id} to {msg.from_user.id}'s spoiler")
|
||||
ready = True
|
||||
|
||||
# elif ((datetime.now() - input_dt).days) < ((datetime.now() - datetime.now().replace(year=datetime.now().year - configGet("age_allowed"))).days):
|
||||
# logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to being underage")
|
||||
# await msg.reply_text(locale("question2_underage", "message").format(str(configGet("age_allowed"))), reply_markup=ForceReply(placeholder=str(locale("question2", "force_reply"))))
|
||||
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")
|
||||
ready = True
|
||||
|
||||
# else:
|
||||
# logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
# await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
# configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
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")
|
||||
ready = True
|
||||
|
||||
# except ValueError:
|
||||
# logWrite(f"User {msg.from_user.id} failed stage {user_stage} due to sending invalid date format")
|
||||
# await msg.reply_text(locale(f"question2_invalid", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage}", "force_reply"))))
|
||||
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": msg.text, "completed": True}} )
|
||||
logWrite(f"Adding text '{msg.text}' to {msg.from_user.id}'s spoiler")
|
||||
ready = True
|
||||
|
||||
if ready is True:
|
||||
await msg.reply_text(locale("spoiler_ready", "message", locale=msg.from_user), reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton(locale("spoiler_send", "button", locale=msg.from_user), switch_inline_query=f"spoiler:{spoiler['_id'].__str__()}")]]))
|
||||
else:
|
||||
await msg.reply_text(locale("spoiler_incorrect_content", "message", locale=msg.from_user))
|
||||
|
||||
# else:
|
||||
# if user_stage <= 9:
|
||||
# logWrite(f"User {msg.from_user.id} completed stage {user_stage} of application")
|
||||
# await msg.reply_text(locale(f"question{user_stage+1}", "message"), reply_markup=ForceReply(placeholder=str(locale(f"question{user_stage+1}", "force_reply"))))
|
||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
# configSet(["stage"], user_stage+1, file=str(msg.from_user.id))
|
||||
# else:
|
||||
# if not configGet("sent", file=str(msg.from_user.id)):
|
||||
# if not configGet("confirmed", file=str(msg.from_user.id)):
|
||||
# configSet(["application", str(user_stage)], str(msg.text), file=str(msg.from_user.id))
|
||||
# application_content = []
|
||||
# i = 1
|
||||
# for question in configGet("application", file=str(msg.from_user.id)):
|
||||
# application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {configGet('application', file=str(msg.from_user.id))[question]}")
|
||||
# i += 1
|
||||
# await msg.reply_text(locale("confirm", "message").format("\n".join(application_content)), reply_markup=ReplyKeyboardMarkup(locale("confirm", "keyboard"), resize_keyboard=True))
|
||||
# #configSet("sent", True, file=str(msg.from_user.id))
|
||||
# #configSet("application_date", int(time()), file=str(msg.from_user.id))
|
||||
# else:
|
||||
# if not configGet("approved", file=str(msg.from_user.id)) and not configGet("rejected", file=str(msg.from_user.id)):
|
||||
# await msg.reply_text(locale("already_sent", "message"))
|
||||
# else:
|
||||
# if not configGet("approved", file=str(msg.from_user.id)) and not configGet("rejected", file=str(msg.from_user.id)):
|
||||
# await msg.reply_text(locale("already_sent", "message"))
|
||||
|
||||
@app.on_message(~ filters.scheduled & filters.group)
|
||||
async def message_in_group(app: Client, msg: Message):
|
||||
if (msg.chat is not None) and (msg.via_bot is not None):
|
||||
if (msg.via_bot.id == (await app.get_me()).id) and (msg.chat.id == configGet("users", "groups")):
|
||||
if msg.text.startswith(locale("spoiler_described", "message").split()[0]) or msg.text.startswith(locale("spoiler_empty", "message").split()[0]):
|
||||
logWrite(f"User {msg.from_user.id} sent spoiler to user's group")
|
||||
try:
|
||||
logWrite("Forwarding spoiler to admin's group")
|
||||
await msg.copy(configGet("admin", "groups"), disable_notification=True)
|
||||
except Exception as exp:
|
||||
logWrite(f"Could not forward spoiler to admin's group due to '{exp}': {print_exc()}")
|
||||
return
|
||||
if configGet("remove_application_time") > 0:
|
||||
logWrite(f"User {msg.from_user.id} requested application in destination group, removing in {configGet('remove_application_time')} minutes")
|
||||
await asyncio.sleep(configGet("remove_application_time")*60)
|
||||
|
@@ -1,15 +0,0 @@
|
||||
from app import app
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import Message
|
||||
from pyrogram.client import Client
|
||||
from classes.holo_user import HoloUser
|
||||
from modules import custom_filters
|
||||
|
||||
@app.on_message(custom_filters.enabled_sponsorships & ~filters.scheduled & filters.photo & filters.private)
|
||||
async def sponsor_proof(app: Client, msg: Message):
|
||||
|
||||
if msg.via_bot is None:
|
||||
|
||||
holo_user = HoloUser(msg.from_user)
|
||||
|
||||
await holo_user.sponsorship_next(msg.text, msg=msg, photo=msg.photo)
|
@@ -13,7 +13,7 @@ for pattern in all_locales("welcome", "keyboard"):
|
||||
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=[""]))
|
||||
async def welcome_pass(app: Client, msg: Message, once_again: bool = True) -> None:
|
||||
async def welcome_pass(app: Client, msg: Message, once_again: bool = False) -> None:
|
||||
"""Set user's stage to 1 and start a fresh application
|
||||
|
||||
### Args:
|
||||
@@ -27,12 +27,11 @@ async def welcome_pass(app: Client, msg: Message, once_again: bool = True) -> No
|
||||
|
||||
holo_user = HoloUser(msg.from_user)
|
||||
|
||||
holo_user.application_restart()
|
||||
if once_again is False:
|
||||
holo_user.application_restart()
|
||||
|
||||
logWrite(f"User {msg.from_user.id} confirmed starting the application")
|
||||
await msg.reply_text(locale("question1", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("question1", "force_reply", locale=msg.from_user)))
|
||||
# configSet(["stage"], 1, file=str(msg.from_user.id))
|
||||
# configSet(["sent"], False, file=str(msg.from_user.id))
|
||||
|
||||
welcome_2 = []
|
||||
for pattern in all_locales("welcome", "keyboard"):
|
||||
|
@@ -9,8 +9,10 @@ from pyrogram.client import Client
|
||||
from pyrogram.enums.chat_type import ChatType
|
||||
from pyrogram.enums.chat_members_filter import ChatMembersFilter
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from classes.holo_user import HoloUser, UserInvalidError, UserNotFoundError
|
||||
from modules.utils import configGet, locale
|
||||
from classes.errors.holo_user import UserNotFoundError, UserInvalidError
|
||||
from classes.holo_user import HoloUser
|
||||
from modules.logging import logWrite
|
||||
from modules.utils import configGet, jsonLoad, locale
|
||||
from modules.database import col_applications, col_spoilers
|
||||
from bson.objectid import ObjectId
|
||||
from bson.errors import InvalidId
|
||||
@@ -28,7 +30,7 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
|
||||
|
||||
if spoil is not None:
|
||||
|
||||
desc = locale("spoiler_empty", "message", locale=inline_query.from_user) if spoil["description"] is None else locale("spoiler_described", "message", locale=inline_query.from_user).format(spoil["description"])
|
||||
desc = locale("spoiler_empty", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories")) if spoil["description"] == "" else locale("spoiler_described", "message", locale=inline_query.from_user).format(locale(spoil["category"], "message", "spoiler_categories"), spoil["description"])
|
||||
|
||||
results = [
|
||||
InlineQueryResultArticle(
|
||||
@@ -63,22 +65,33 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
|
||||
)
|
||||
return
|
||||
|
||||
results_forbidden = [
|
||||
InlineQueryResultArticle(
|
||||
title=locale("title", "inline", "forbidden", locale=inline_query.from_user),
|
||||
input_message_content=InputTextMessageContent(
|
||||
locale("message_content", "inline", "forbidden", locale=inline_query.from_user)
|
||||
),
|
||||
description=locale("description", "inline", "forbidden", locale=inline_query.from_user)
|
||||
)
|
||||
]
|
||||
|
||||
try:
|
||||
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=[
|
||||
InlineQueryResultArticle(
|
||||
title=locale("title", "inline", "forbidden", locale=inline_query.from_user),
|
||||
input_message_content=InputTextMessageContent(
|
||||
locale("message_content", "inline", "forbidden", locale=inline_query.from_user)
|
||||
),
|
||||
description=locale("description", "inline", "forbidden", locale=inline_query.from_user)
|
||||
)
|
||||
]
|
||||
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
|
||||
)
|
||||
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
|
||||
@@ -160,5 +173,6 @@ async def inline_answer(client: Client, inline_query: InlineQuery):
|
||||
|
||||
await inline_query.answer(
|
||||
results=results,
|
||||
cache_time=10
|
||||
)
|
||||
cache_time=10,
|
||||
is_personal=True
|
||||
)
|
@@ -4,8 +4,9 @@ some scheduled tasks is the main idea of this module"""
|
||||
from os import listdir, makedirs, path, sep
|
||||
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
|
||||
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,8 +22,10 @@ if configGet("enabled", "scheduler", "cache_members"):
|
||||
list_of_users = []
|
||||
async for member in app.get_chat_members(configGet("users", "groups")):
|
||||
list_of_users.append(member.user.id)
|
||||
makedirs("cache", exist_ok=True)
|
||||
makedirs(configGet("cache", "locations"), exist_ok=True)
|
||||
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"))
|
||||
@@ -30,12 +33,14 @@ if configGet("enabled", "scheduler", "cache_admins"):
|
||||
list_of_users = []
|
||||
async for member in app.get_chat_members(configGet("admin", "groups")):
|
||||
list_of_users.append(member.user.id)
|
||||
makedirs("cache", exist_ok=True)
|
||||
makedirs(configGet("cache", "locations"), exist_ok=True)
|
||||
jsonSave(list_of_users, path.join(configGet("cache", "locations"), "admins"))
|
||||
if configGet("debug") is True:
|
||||
logWrite("Admin group caching performed", debug=True)
|
||||
|
||||
# Cache the avatars of group members
|
||||
if configGet("enabled", "scheduler", "cache_avatars"):
|
||||
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=10))
|
||||
@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 = []
|
||||
@@ -75,7 +80,7 @@ if configGet("enabled", "features", "sponsorships") is True:
|
||||
try:
|
||||
tg_user = await app.get_users(entry["user"])
|
||||
until_expiry = relativedelta(datetime.now(), entry["sponsorship"]["expires"]).days
|
||||
await app.send_message( tg_user, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore
|
||||
await app.send_message( tg_user.id, locale("sponsorships_expires", "message").format(until_expiry) ) # type: ignore
|
||||
logWrite(f"Notified user that sponsorship expires in {until_expiry} days")
|
||||
except Exception as exp:
|
||||
logWrite(f"Could not find user {entry['user']} notify about sponsorship expiry due to '{exp}'")
|
||||
@@ -98,14 +103,26 @@ if configGet("enabled", "features", "sponsorships") is True:
|
||||
|
||||
|
||||
# Register all bot commands
|
||||
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=3))
|
||||
@scheduler.scheduled_job(trigger="date", run_date=datetime.now()+timedelta(seconds=10))
|
||||
async def commands_register():
|
||||
|
||||
commands = {
|
||||
"users": [],
|
||||
"admins": [],
|
||||
"owner": [],
|
||||
"group_users": [],
|
||||
"group_admins": [],
|
||||
"group_users_admins": [],
|
||||
"locales": {}
|
||||
}
|
||||
|
||||
commands_raw = {
|
||||
"users": [],
|
||||
"admins": [],
|
||||
"owner": [],
|
||||
"group_users": [],
|
||||
"group_admins": [],
|
||||
"group_users_admins": [],
|
||||
"locales": {}
|
||||
}
|
||||
|
||||
@@ -118,9 +135,20 @@ async def commands_register():
|
||||
commands["locales"][".".join(entry.split(".")[:-1])] = {
|
||||
"users": [],
|
||||
"admins": [],
|
||||
"owner": [],
|
||||
"group_users": [],
|
||||
"group_admins": []
|
||||
"group_admins": [],
|
||||
"group_users_admins": []
|
||||
}
|
||||
if configGet("debug") is True:
|
||||
commands_raw["locales"][".".join(entry.split(".")[:-1])] = {
|
||||
"users": [],
|
||||
"admins": [],
|
||||
"owner": [],
|
||||
"group_users": [],
|
||||
"group_admins": [],
|
||||
"group_users_admins": []
|
||||
}
|
||||
|
||||
config_modules = configGet("features")
|
||||
config_commands = configGet("commands")
|
||||
@@ -135,13 +163,25 @@ async def commands_register():
|
||||
enabled = True
|
||||
|
||||
if enabled is False:
|
||||
logWrite(f"Not registering {command} at all", debug=True)
|
||||
continue
|
||||
|
||||
for permission in config_commands[command]["permissions"]:
|
||||
|
||||
commands[permission].append(BotCommand(command, locale("commands")[command]))
|
||||
|
||||
if configGet("debug") is True:
|
||||
commands_raw[permission].append({f"{command}": locale("commands")[command]})
|
||||
logWrite(f"Registering {command} for {permission}")
|
||||
|
||||
for lc in valid_locales:
|
||||
|
||||
commands["locales"][lc][permission].append(BotCommand(command, locale("commands", locale=lc)[command]))
|
||||
|
||||
if configGet("debug") is True:
|
||||
commands_raw["locales"][lc][permission].append({f"{command}": locale("commands", locale=lc)[command]})
|
||||
logWrite(f"Registering {command} for {permission} [{lc}]")
|
||||
|
||||
|
||||
# Registering user commands
|
||||
await app.set_bot_commands(commands["users"])
|
||||
@@ -152,17 +192,23 @@ async def commands_register():
|
||||
await app.set_bot_commands(commands["locales"][lc]["users"], language_code=lc)
|
||||
logWrite(f"Registered user commands for locale {lc}")
|
||||
|
||||
# Registering admin/owner commands
|
||||
for admin in configGet("admins")+[configGet("owner")]:
|
||||
# Registering admin commands
|
||||
for admin in configGet("admins"):
|
||||
try:
|
||||
await app.set_bot_commands(commands["admins"], scope=BotCommandScopeChat(chat_id=admin))
|
||||
if admin == configGet("owner"):
|
||||
logWrite(f"Registered admin commands for owner {configGet('owner')}")
|
||||
else:
|
||||
logWrite(f"Registered admin commands for admin {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")))
|
||||
for lc in valid_locales:
|
||||
await app.set_bot_commands(commands["locales"][lc]["admins"]+commands["locales"][lc]["owner"]+commands["locales"][lc]["users"], scope=BotCommandScopeChat(chat_id=configGet("owner")))
|
||||
logWrite(f"Registered admin commands for owner {configGet('owner')}")
|
||||
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")))
|
||||
@@ -175,4 +221,16 @@ async def commands_register():
|
||||
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")))
|
||||
logWrite("Registered destination group admin commands")
|
||||
except bad_request_400.ChannelInvalid:
|
||||
logWrite(f"Could not register admin commands for destination group. Bot is likely not in the group.")
|
||||
|
||||
|
||||
if configGet("debug") is True:
|
||||
print(commands, flush=True)
|
||||
logWrite(f"Complete commands registration:\n{dumps(commands_raw, indent=4, ensure_ascii=False, encode_html_chars=False)}", debug=True)
|
@@ -1,10 +1,11 @@
|
||||
APScheduler==3.9.1.post1
|
||||
fastapi==0.88.0
|
||||
fastapi~=0.88.0
|
||||
psutil==5.9.4
|
||||
pymongo==4.3.3
|
||||
Pyrogram==2.0.69
|
||||
Pyrogram~=2.0.96
|
||||
requests==2.28.1
|
||||
tgcrypto==1.2.5
|
||||
python_dateutil==2.8.2
|
||||
starlette==0.22.0
|
||||
ujson==5.6.0
|
||||
starlette~=0.22.0
|
||||
ujson~=5.7.0
|
||||
ftfy~=6.1.1
|
64
validation/spoilers.json
Normal file
64
validation/spoilers.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"$jsonSchema": {
|
||||
"required": [
|
||||
"user",
|
||||
"completed",
|
||||
"category",
|
||||
"description",
|
||||
"photo",
|
||||
"video",
|
||||
"audio",
|
||||
"animation",
|
||||
"document",
|
||||
"caption",
|
||||
"text"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"bsonType": ["int", "long"],
|
||||
"description": "Telegram ID of user"
|
||||
},
|
||||
"completed": {
|
||||
"bsonType": "bool",
|
||||
"description": "Whether spoiler is a completed one"
|
||||
},
|
||||
"category": {
|
||||
"bsonType": ["string", "null"],
|
||||
"enum": ["nsfw", "deanon", "other"],
|
||||
"description": "Spoiler's category"
|
||||
},
|
||||
"description": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Spoiler's description"
|
||||
},
|
||||
"photo": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Spoilered photo"
|
||||
},
|
||||
"video": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Spoilered video"
|
||||
},
|
||||
"audio": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Spoilered audio"
|
||||
},
|
||||
"animation": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Spoilered animation/GIF"
|
||||
},
|
||||
"document": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Spoilered document/file"
|
||||
},
|
||||
"caption": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Spoilered caption for media"
|
||||
},
|
||||
"text": {
|
||||
"bsonType": ["string", "null"],
|
||||
"description": "Spoilered text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -33,7 +33,7 @@
|
||||
"bsonType": "date"
|
||||
},
|
||||
"sponsorship.proof": {
|
||||
"bsonType": "binData"
|
||||
"bsonType": "string"
|
||||
},
|
||||
"sponsorship.label": {
|
||||
"bsonType": "string"
|
||||
|
Reference in New Issue
Block a user