This commit is contained in:
Profitroll 2022-11-22 15:26:37 +01:00
commit efcb60ed95
3 changed files with 103 additions and 36 deletions

View File

@ -1,12 +1,4 @@
{ {
"commands": {
"start": "Почати користуватись ботом",
"rules": "Правила пропонування фото"
},
"commands_admin": {
"forwards": "Переглянути репости",
"reboot": "Перезапустити бота"
},
"message": { "message": {
"start": "Привіт і ласкаво просимо!\n\nЦей бот створено для прийому заявок на вступ до нашої спільноти. Для продовження нас цікавить відповідь на одне питання:\n\nЧи хочеш ти доєднатися до українського ком'юніті фанатів Хололайв?", "start": "Привіт і ласкаво просимо!\n\nЦей бот створено для прийому заявок на вступ до нашої спільноти. Для продовження нас цікавить відповідь на одне питання:\n\nЧи хочеш ти доєднатися до українського ком'юніті фанатів Хололайв?",
"goodbye": "Добре, дякуємо за чесність! Вибачте, але за таких умов ми не будемо тебе додавати до спільноти. Якщо передумаєш та захочеш приєднатись - просто натисни на кнопку.", "goodbye": "Добре, дякуємо за чесність! Вибачте, але за таких умов ми не будемо тебе додавати до спільноти. Якщо передумаєш та захочеш приєднатись - просто натисни на кнопку.",
@ -55,6 +47,12 @@
"reapply_in_progress": "❌ **Дія неможлива**\nТи прямо зараз вже заповнюєш анкету. Якщо в ній є помилка - після заповнення просто натисни **{0}** та почни знову.", "reapply_in_progress": "❌ **Дія неможлива**\nТи прямо зараз вже заповнюєш анкету. Якщо в ній є помилка - після заповнення просто натисни **{0}** та почни знову.",
"birthday": "У користувача **{0}** (@{1}) сьогодні день народження! Виповнилось {2} років", "birthday": "У користувача **{0}** (@{1}) сьогодні день народження! Виповнилось {2} років",
"application_invalid_syntax": "Неправильний синтаксис!\nТреба: `/application ID/NAME/USERNAME`", "application_invalid_syntax": "Неправильний синтаксис!\nТреба: `/application ID/NAME/USERNAME`",
"warned": "Попереджено користувача **{0}** (`{1}`) про порушення правил",
"warnings_1": "Користувач **{0}** (`{1}`) має **{2}** попередження",
"warnings_2": "Користувач **{0}** (`{1}`) має **{2}** попереджень",
"no_warnings": "Користувач **{0}** (`{1}`) не має попереджень",
"no_user_warnings": "Не знайдено користувачів за запитом **{0}**",
"syntax_warnings": "Неправильний синтаксис!\nТреба: `/warnings ID/NAME/USERNAME`",
"question_titles": { "question_titles": {
"question1": "Ім'я/звертання:", "question1": "Ім'я/звертання:",
"question2": "День народження:", "question2": "День народження:",

108
main.py
View File

@ -20,7 +20,7 @@ from pyrogram.errors.exceptions import bad_request_400
pid = getpid() pid = getpid()
for entry in [f"{configGet('data', 'locations')}{sep}applications.json"]: for entry in [f"{configGet('data', 'locations')}{sep}applications.json", f"{configGet('data', 'locations')}{sep}warnings.json"]:
mode = 'r' if path.exists(entry) else 'w' mode = 'r' if path.exists(entry) else 'w'
with open(entry, mode) as f: with open(entry, mode) as f:
try: try:
@ -50,10 +50,10 @@ async def cmd_start(app, msg):
# Shutdown command ============================================================================================================= # Shutdown command =============================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["", "/"])) @app.on_message(~ filters.scheduled & filters.private & filters.command(["kill", "die", "reboot"], prefixes=["/"]))
async def cmd_kill(app, msg): async def cmd_kill(app, msg):
if await isAnAdmin(msg.from_user.id): if msg.chat.id == configGet("admin_group") or await isAnAdmin(msg.from_user.id):
logWrite(f"Shutting down bot with pid {pid}") logWrite(f"Shutting down bot with pid {pid}")
await msg.reply_text(f"Вимкнення бота з підом `{pid}`") await msg.reply_text(f"Вимкнення бота з підом `{pid}`")
killProc(pid) killProc(pid)
@ -61,28 +61,82 @@ async def cmd_kill(app, msg):
# Rules command ============================================================================================================= # Rules command =============================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["rules"], prefixes=["", "/"])) @app.on_message(~ filters.scheduled & filters.private & filters.command(["rules"], prefixes=["/"]))
async def cmd_rules(app, msg): async def cmd_rules(app, msg):
for rule_msg in locale("rules"): for rule_msg in locale("rules"):
await msg.reply_text(rule_msg) await msg.reply_text(rule_msg)
# ============================================================================================================================== # ==============================================================================================================================
# Warn command =============================================================================================================
@app.on_message(~ filters.scheduled & filters.command(["warn"], prefixes=["/"]))
async def cmd_warn(app, msg):
if msg.chat.id == configGet("destination_group"):
if msg.reply_to_message_id != None:
if isAnAdmin(msg.from_user.id):
warnings = jsonLoad(f"{configGet('data', 'locations')}{sep}warnings.json")
if str(msg.reply_to_message.from_user.id) not in warnings:
warnings[str(msg.reply_to_message.from_user.id)] = 1
else:
warnings[str(msg.reply_to_message.from_user.id)] += 1
jsonSave(warnings, f"{configGet('data', 'locations')}{sep}warnings.json")
await msg.reply_text(locale("warned", "message").format(msg.reply_to_message.from_user.first_name, msg.reply_to_message.from_user.id)) # type: ignore
# ==============================================================================================================================
# Warnings command =============================================================================================================
@app.on_message(~ filters.scheduled & filters.command(["warnings"], prefixes=["/"]))
async def cmd_warnings(app, msg):
if msg.chat.id == configGet("admin_group") or await isAnAdmin(msg.from_user.id):
warnings = jsonLoad(f"{configGet('data', 'locations')}{sep}warnings.json")
if len(msg.command) <= 1:
await msg.reply_text(locale("syntax_warnings", "message"))
if path.exists(f"{configGet('data', 'locations')}{sep}users{sep}{msg.command[1]}.json"):
target_id = str(int(msg.command[1]))
target_name = "N/A"
else:
list_of_users = []
async for m in app.get_chat_members(configGet("destination_group"), filter=ChatMembersFilter.SEARCH, query=msg.command[1]):
list_of_users.append(m)
if len(list_of_users) != 0:
target = list_of_users[0].user
target_name = target.first_name
target_id = str(target.id)
else:
await msg.reply_text(locale("no_user_warnings", "message").format(msg.command[1])) # type: ignore
return
if target_id not in warnings:
await msg.reply_text(locale("no_warnings", "message").format(target_name, target_id)) # type: ignore
else:
if warnings[target_id] <= 5:
await msg.reply_text(locale("warnings_1", "message").format(target_name, target_id, warnings[target_id])) # type: ignore
else:
await msg.reply_text(locale("warnings_2", "message").format(target_name, target_id, warnings[target_id])) # type: ignore
# ==============================================================================================================================
# Applications command ========================================================================================================= # Applications command =========================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["applications"], prefixes=["", "/"])) @app.on_message(~ filters.scheduled & filters.command(["applications"], prefixes=["/"]))
async def cmd_applications(app, msg): async def cmd_applications(app, msg):
if await isAnAdmin(msg.from_user.id): if (await isAnAdmin(msg.from_user.id)) or (msg.chat.id == configGet("admin_group")):
await app.send_chat_action(msg.chat.id, ChatAction.UPLOAD_DOCUMENT) await app.send_chat_action(msg.chat.id, ChatAction.UPLOAD_DOCUMENT)
await msg.reply_document(document=f"{configGet('data', 'locations')}{sep}applications.json") await msg.reply_document(document=f"{configGet('data', 'locations')}{sep}applications.json")
# ============================================================================================================================== # ==============================================================================================================================
# Applications command ========================================================================================================= # Applications command =========================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["application"], prefixes=["", "/"])) @app.on_message(~ filters.scheduled & filters.command(["application"], prefixes=["/"]))
async def cmd_application(app, msg): async def cmd_application(app, msg):
if await isAnAdmin(msg.from_user.id): if (await isAnAdmin(msg.from_user.id)) or (msg.chat.id == configGet("admin_group")):
try: try:
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"]): 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]) user_id = int(msg.command[1])
@ -92,17 +146,17 @@ async def cmd_application(app, msg):
list_of_users.append(m) list_of_users.append(m)
user_id = list_of_users[0].user.id user_id = list_of_users[0].user.id
try: try:
user_data = jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{user_id.user.id}.json") user_data = jsonLoad(f"{configGet('data', 'locations')}{sep}users{sep}{user_id}.json")
application_content = [] application_content = []
i = 1 i = 1
for question in configGet("application", file=str(msg.from_user.id)): for question in configGet("application", file=str(msg.from_user.id)):
if i == 2: if i == 2:
age = relativedelta(datetime.now(), datetime.strptime(configGet('application', file=str(user_id.user.id))['2'], '%d.%m.%Y')) age = relativedelta(datetime.now(), datetime.strptime(configGet('application', file=str(user_id))['2'], '%d.%m.%Y'))
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {configGet('application', file=str(user_id.user.id))['2']} ({age.years} р.)") application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {configGet('application', file=str(user_id))['2']} ({age.years} р.)")
else: else:
application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {configGet('application', file=str(user_id.user.id))[question]}") application_content.append(f"{locale('question'+str(i), 'message', 'question_titles')} {configGet('application', file=str(user_id))[question]}")
i += 1 i += 1
application = jsonLoad(f"{configGet('data', 'locations')}{sep}applications.json")[str(user_id.user.id)] application = jsonLoad(f"{configGet('data', 'locations')}{sep}applications.json")[str(user_id)]
if user_data["sent"]: if user_data["sent"]:
if user_data["approved"]: 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")) # type: ignore 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")) # type: ignore
@ -117,10 +171,10 @@ async def cmd_application(app, msg):
application_status = locale("application_status_refused", "message").format((await app.get_users(application["refused_by"])).first_name, datetime.fromtimestamp(application["refusal_date"]).strftime("%d.%m.%Y, %H:%M")) # type: ignore application_status = locale("application_status_refused", "message").format((await app.get_users(application["refused_by"])).first_name, datetime.fromtimestamp(application["refusal_date"]).strftime("%d.%m.%Y, %H:%M")) # type: ignore
else: else:
application_status = locale("application_status_not_send", "message") application_status = locale("application_status_not_send", "message")
logWrite(f"User {msg.from_user.id} requested application of {user_id.user.id}") logWrite(f"User {msg.from_user.id} requested application of {user_id}")
await msg.reply_text(locale("contact", "message").format(str(user_id.user.id), "\n".join(application_content), application_status)) # type: ignore await msg.reply_text(locale("contact", "message").format(str(user_id), "\n".join(application_content), application_status)) # type: ignore
except FileNotFoundError: except FileNotFoundError:
logWrite(f"User {msg.from_user.id} requested application of {user_id.user.id} but user does not exists") logWrite(f"User {msg.from_user.id} requested application of {user_id} but user does not exists")
await msg.reply_text(locale("contact_invalid", "message")) await msg.reply_text(locale("contact_invalid", "message"))
except IndexError: except IndexError:
@ -129,7 +183,7 @@ async def cmd_application(app, msg):
# Reapply command ============================================================================================================== # Reapply command ==============================================================================================================
@app.on_message(~ filters.scheduled & filters.private & filters.command(["reapply"], prefixes=["", "/"])) @app.on_message(~ filters.scheduled & filters.private & filters.command(["reapply"], prefixes=["/"]))
async def cmd_reapply(app, msg): async def cmd_reapply(app, msg):
if configGet("approved", file=str(msg.from_user.id)) or configGet("refused", file=str(msg.from_user.id)): if configGet("approved", file=str(msg.from_user.id)) or configGet("refused", file=str(msg.from_user.id)):
@ -138,12 +192,12 @@ async def cmd_reapply(app, msg):
configSet("confirmed", False, file=str(msg.from_user.id)) configSet("confirmed", False, file=str(msg.from_user.id))
await welcome_pass(app, msg, once_again=True) await welcome_pass(app, msg, once_again=True)
else: else:
await msg.reply_text(locale("reapply_in_progress", "message").format(locale("confirm", "keyboard")[1][0])) await msg.reply_text(locale("reapply_in_progress", "message").format(locale("confirm", "keyboard")[1][0])) # type: ignore
else: else:
if configGet("sent", file=str(msg.from_user.id)): if configGet("sent", file=str(msg.from_user.id)):
await msg.reply_text(locale("reapply_forbidden", "message")) await msg.reply_text(locale("reapply_forbidden", "message"))
else: else:
await msg.reply_text(locale("reapply_in_progress", "message").format(locale("confirm", "keyboard")[1][0])) await msg.reply_text(locale("reapply_in_progress", "message").format(locale("confirm", "keyboard")[1][0])) # type: ignore
# ============================================================================================================================== # ==============================================================================================================================
@ -380,7 +434,7 @@ async def callback_query_refuse(app, clb):
# Callbacks application ======================================================================================================== # Callbacks application ========================================================================================================
@app.on_callback_query(filters.regex("reapply_yes_[\s\S]*")) # type: ignore @app.on_callback_query(filters.regex("reapply_yes_[\s\S]*")) # type: ignore
async def callback_query_accept(app, clb): async def callback_reapply_query_accept(app, clb):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
@ -404,7 +458,7 @@ async def callback_query_accept(app, clb):
await clb.answer(text=locale("sub_accepted", "callback").format(fullclb[2]), show_alert=True) # type: ignore await clb.answer(text=locale("sub_accepted", "callback").format(fullclb[2]), show_alert=True) # type: ignore
@app.on_callback_query(filters.regex("reapply_no_[\s\S]*")) # type: ignore @app.on_callback_query(filters.regex("reapply_no_[\s\S]*")) # type: ignore
async def callback_query_refuse(app, clb): async def callback_query_reapply_refuse(app, clb):
fullclb = clb.data.split("_") fullclb = clb.data.split("_")
@ -669,6 +723,18 @@ if __name__ == "__main__":
app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=configGet("owner"))) # type: ignore app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=configGet("owner"))) # type: ignore
# Registering admin group commands
commands_group_admin_list = []
for command in configGet("commands_group_admin"):
commands_group_admin_list.append(BotCommand(command, configGet("commands_group_admin")[command]))
app.set_bot_commands(commands_group_admin_list, scope=BotCommandScopeChat(chat_id=configGet("admin_group"))) # type: ignore
# Registering destination group commands
commands_group_destination_list = []
for command in configGet("commands_group_destination"):
commands_group_destination_list.append(BotCommand(command, configGet("commands_group_destination")[command]))
app.set_bot_commands(commands_group_destination_list, scope=BotCommandScopeChat(chat_id=configGet("destination_group"))) # type: ignore
idle() idle()
app.send_message(configGet("owner"), f"Shutting with pid `{pid}`") # type: ignore app.send_message(configGet("owner"), f"Shutting with pid `{pid}`") # type: ignore

View File

@ -20,7 +20,6 @@ def jsonLoad(filename):
except FileNotFoundError: except FileNotFoundError:
logWrite(f"Could not load json file {filename}: file does not seem to exist!\n{print_exc()}") logWrite(f"Could not load json file {filename}: file does not seem to exist!\n{print_exc()}")
raise raise
file.close()
return output return output
def jsonSave(contents, filename): def jsonSave(contents, filename):
@ -28,7 +27,6 @@ def jsonSave(contents, filename):
try: try:
with open(filename, "w", encoding='utf8') as file: with open(filename, "w", encoding='utf8') as file:
file.write(dumps(contents, ensure_ascii=False, indent=4)) file.write(dumps(contents, ensure_ascii=False, indent=4))
file.close()
except Exception as exp: except Exception as exp:
logWrite(f"Could not save json file {filename}: {exp}\n{print_exc()}") logWrite(f"Could not save json file {filename}: {exp}\n{print_exc()}")
return return
@ -44,7 +42,8 @@ def configSet(key: str, value, *args: str, file: str = "config"):
""" """
if file == "config": if file == "config":
filepath = "" filepath = ""
if this_dict["debug"]: this_dict = jsonLoad(f"{filepath}{file}.json")
if this_dict["debug"] is True:
try: try:
this_dict = jsonLoad("config_debug.json") this_dict = jsonLoad("config_debug.json")
file = "config_debug" file = "config_debug"
@ -52,12 +51,16 @@ def configSet(key: str, value, *args: str, file: str = "config"):
print("Debug mode is set but config_debug.json is not there! Falling back to config.json", flush=True) print("Debug mode is set but config_debug.json is not there! Falling back to config.json", flush=True)
else: else:
filepath = f"data{sep}users{sep}" filepath = f"data{sep}users{sep}"
this_dict = jsonLoad(f"{filepath}{file}.json") this_dict = jsonLoad(f"{filepath}{file}.json")
string = "this_dict" string = "this_dict"
for arg in args: for arg in args:
string += f'["{arg}"]' string += f'["{arg}"]'
if type(value) in [str]: if type(value) in [str]:
string += f'["{key}"] = "{value}"' value.replace("'", "\'").replace('"', '\"')
#if len(value) < 30:
# string += f'["{key}"] = "{value}"'
#else:
string += f'["{key}"] = """{value}"""'
else: else:
string += f'["{key}"] = {value}' string += f'["{key}"] = {value}'
exec(string) exec(string)
@ -79,7 +82,7 @@ def configGet(key: str, *args: str, file: str = "config"):
except FileNotFoundError: except FileNotFoundError:
print("Config file not found! Copy config_example.json to config.json, configure it and rerun the bot!", flush=True) print("Config file not found! Copy config_example.json to config.json, configure it and rerun the bot!", flush=True)
exit() exit()
if this_dict["debug"]: if this_dict["debug"] is True:
try: try:
this_dict = jsonLoad("config_debug.json") this_dict = jsonLoad("config_debug.json")
except FileNotFoundError: except FileNotFoundError: