Locales added

This commit is contained in:
Profitroll 2022-10-20 12:24:32 +02:00
parent 29d725e6db
commit b173544506
6 changed files with 149 additions and 38 deletions

View File

@ -5,10 +5,10 @@
1. Лінка веде на бота. 1. Лінка веде на бота.
2. Перший пост від бота: вітання та питання, чи хоче людина доєднатися до українського ком'юніті фанатів Хололайва 2. Перший пост від бота: вітання та питання, чи хоче людина доєднатися до українського ком'юніті фанатів Хололайва
3. Дві кнопки: "Так-Ні" 3. Дві кнопки: "Так-Ні"
3а. Якщо "Ні", то бот вибачається та каже, що, коли захоче, то людина фрі ту джоін. Під цим кнопка "Я передумав, я хочу" * Якщо "Ні", то бот вибачається та каже, що, коли захоче, то людина фрі ту джоін. Під цим кнопка "Я передумав, я хочу"
4. Якщо "Так", бот кидає анкету та просить заповнити за пунктами. Після цього наступна відповідь людини пересилається в чат ХолоКиїв (лінку дамо тобі) 4. Якщо "Так", бот кидає анкету та просить заповнити за пунктами. Після цього наступна відповідь людини пересилається в чат ХолоКиїв (лінку дамо тобі)
5. З адмінської сторони має бути доступ до бота з окремим адмін-доступом, де можна для кожного юзера, який відправив анкету ботові, натиснути кнопку апрув або дінай 5. З адмінської сторони має бути доступ до бота з окремим адмін-доступом, де можна для кожного юзера, який відправив анкету ботові, натиснути кнопку апрув або дінай
5а. Якщо дінай, бот вибачається та каже повертатися, коли буде бажання втягнутися * Якщо дінай, бот вибачається та каже повертатися, коли буде бажання втягнутися
6. Якщо апрув, бот кидає лінку до чату 6. Якщо апрув, бот кидає лінку до чату
Можно кидать не просто "заполните анкету", а что бы бот поочерёдно задавал вопросы. И после каждого ответа, он их сохранял в отдельное облако ответов Можно кидать не просто "заполните анкету", а что бы бот поочерёдно задавал вопросы. И после каждого ответа, он их сохранял в отдельное облако ответов

View File

@ -1,4 +1,5 @@
{ {
"locale": "uk",
"owner": 0, "owner": 0,
"admins": [], "admins": [],
"bot": { "bot": {

23
data/user_default.json Normal file
View File

@ -0,0 +1,23 @@
{
"stage": 0,
"link": null,
"approved": false,
"approved_by": null,
"application_date": null,
"approval_date": null,
"telegram_id": null,
"telegram_name": null,
"telegram_phone": null,
"application": {
"1": null,
"2": null,
"3": null,
"4": null,
"5": null,
"6": null,
"7": null,
"8": null,
"9": null,
"10": null
}
}

61
locale/uk.json Normal file
View File

@ -0,0 +1,61 @@
{
"commands": {
"start": "Почати користуватись ботом",
"rules": "Правила пропонування фото"
},
"commands_admin": {
"forwards": "Переглянути репости",
"reboot": "Перезапустити бота"
},
"message": {
"start": "Привіт і ласкаво просимо!\n\nЦей бот створено для прийому заявок на вступ до нашої спільноти. Для продовження нас цікавить відповідь на одне питання:\n\nЧи хочеш ти доєднатися до українського ком'юніті фанатів Хололайв?",
"goodbye": "Добре, дякуємо за чесність! Вибачте, але за таких умов ми не будемо тебе додавати до спільноти. Якщо передумаєш та захочеш приєднатись - просто натисни на кнопку.",
"privacy_notice": "Раді це чути!\n\nДля продовження треба буде заповнити невеличку анкетку. Будь ласка, віднесись до цього серйозно. Ми відповідально ставимось до персональних даних, тому ця анкета не буде передана третім особам, а буде використана лише для проходження до спільноти.",
"question1": "Як до тебе можна звертатись?",
"question2": "Скільки тобі років?",
"question3": "З якого ти міста та де проживаєш зараз?\n\n⚠ Будь ласка, не вказуйте точних адрес! \"Київщина\" може бути достатньою конкретизацією.",
"question4": "Коли вперше довелось дізнатись про Хололайв?",
"question5": "Чим тебе зацікавив Хололайв?",
"question6": "Контент якої дівчини тобі подобається найбільше?",
"question7": "Назви контент хоча б п'яти японських холодівчат, які тобі подобаються найбільше.",
"question8": "Чи дивишся ти стріми дівчат Хололайву?",
"question9": "Чиї пісні з Хололайву тобі подобаються найбільше?",
"question10": "Ну і нарешті, розкажи трохи про себе. Про хобі, чим тобі подобається займатись. Одним повідомленням, будь ласка.",
"question2_underage": "Вибач, але треба досягти віку {0} років, щоб приєднатись до нас. Такі обмеження існують для того, щоб всім у спільноті було цікаво одне з одним.",
"question2_invalid": "Будь ласка, введи ціле число.",
"question2_joke": "Тижпрограміст, ми так і поняли. Але будь ласка, введи реальне значення.",
"shutdown": "Вимкнення бота з підом `{0}`",
"startup": "Запуск бота з підом `{0}`",
"startup_downtime": "Запуск бота з підом `{0}` (лежав {1})",
"sub_yes": "✅ Подання схвалено та прийнято",
"sub_no": "❌ Подання розглянуто та відхилено"
},
"keyboards": {
"welcome": [
[
"Так, звісно"
],
[
"Ні, дякую"
]
],
"return": [
[
"Я передумав, я хочу"
]
]
},
"force_reply": {
"question1": "Ім'я або звертання"
},
"button": {
"sub_yes": "✅ Прийняти",
"sub_no": "❌ Відхилити",
"accepted": "✅ Прийнято",
"declined": "❌ Відхилено"
},
"callback": {
"sub_yes": "✅ Подання схвалено",
"sub_no": "❌ Подання відхилено"
}
}

23
main.py
View File

@ -4,7 +4,7 @@ from modules.utils import *
from pyrogram.client import Client from pyrogram.client import Client
from pyrogram import filters from pyrogram import filters
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, BotCommand, BotCommandScopeChat from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, BotCommand, BotCommandScopeChat, ReplyKeyboardMarkup, ForceReply
from pyrogram import idle # type: ignore from pyrogram import idle # type: ignore
from pyrogram.errors.exceptions import bad_request_400 from pyrogram.errors.exceptions import bad_request_400
@ -12,6 +12,19 @@ pid = getpid()
app = Client("holochecker", bot_token=configGet("bot_token", "bot"), api_id=configGet("api_id", "bot"), api_hash=configGet("api_hash", "bot")) app = Client("holochecker", bot_token=configGet("bot_token", "bot"), api_id=configGet("api_id", "bot"), api_hash=configGet("api_hash", "bot"))
@app.on_message(~ filters.scheduled & filters.command(["start"], prefixes=["/"]))
async def cmd_start(app, msg):
try:
user_conf = configGet("stage", file=str(msg.from_user.id))
if user_conf["stage"] != 0:
return
except FileNotFoundError:
jsonSave(jsonLoad(f"data{sep}user_default.json"), f"data{sep}users{sep}{msg.from_user.id}.json")
user_conf = configGet("stage", file=str(msg.from_user.id))
await msg.reply_text(locale("start"), reply_markup=ReplyKeyboardMarkup(locale("welcome", "keyboards")))
@app.on_message(~ filters.scheduled & filters.command(["kill", "die", "reboot"], prefixes=["", "/"])) @app.on_message(~ filters.scheduled & filters.command(["kill", "die", "reboot"], prefixes=["", "/"]))
async def cmd_kill(app, msg): async def cmd_kill(app, msg):
@ -20,13 +33,19 @@ async def cmd_kill(app, msg):
await msg.reply_text(f"Вимкнення бота з підом `{pid}`") await msg.reply_text(f"Вимкнення бота з підом `{pid}`")
killProc(pid) killProc(pid)
@app.on_message(~ filters.scheduled & (filters.regex(locale("welcome", "keyboards")[0][0]) | filters.regex(locale("return", "keyboards")[0][0])))
async def any_message(app, msg):
await msg.reply_text(locale("privacy_notice", "message"))
await msg.reply_text(locale("question1", "message"), reply_markup=ForceReply(placeholder=locale("question1", "force_reply")))
if __name__ == "__main__": if __name__ == "__main__":
logWrite(f"Starting up with pid {pid}") logWrite(f"Starting up with pid {pid}")
# Yes, it should be in some kind of async main() function but I don't give a shit. # Yes, it should be in some kind of async main() function but I don't give a shit.
# I did compare performance and it's much more useful this way. Change my mind. # I did compare performance, almost no difference and it's much more useful this way. Change my mind.
app.start() # type: ignore app.start() # type: ignore
app.send_message(configGet("owner"), f"Starting up with pid `{pid}`") # type: ignore app.send_message(configGet("owner"), f"Starting up with pid `{pid}`") # type: ignore

View File

@ -1,8 +1,9 @@
from typing import Union
from ujson import JSONDecodeError as JSONDecodeError from ujson import JSONDecodeError as JSONDecodeError
from ujson import loads, dumps from ujson import loads, dumps
from sys import exit from sys import exit
from os import kill from os import kill, sep
from os import name as osname from os import name as osname
from traceback import print_exc from traceback import print_exc
@ -33,14 +34,19 @@ def jsonSave(contents, filename):
return return
def configSet(key: str, value, *args: str): def configSet(key: str, value, *args: str, file: str = "config"):
"""Set key to a value """Set key to a value
Args: Args:
* key (str): The last key of the keys path. * key (str): The last key of the keys path.
* value (str/int/float/list/dict/None): Some needed value. * value (str/int/float/list/dict/None): Some needed value.
* *args (str): Path to key like: dict[args][key]. * *args (str): Path to key like: dict[args][key].
* file (str): User ID to save. Saved to config if not provided. Defaults to "config".
""" """
this_dict = jsonLoad("config.json") if file == "config":
filepath = ""
else:
filepath = f"data{sep}users{sep}"
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}"]'
@ -49,54 +55,55 @@ def configSet(key: str, value, *args: str):
else: else:
string += f'["{key}"] = {value}' string += f'["{key}"] = {value}'
exec(string) exec(string)
jsonSave(this_dict, "config.json") jsonSave(this_dict, f"{filepath}{file}.json")
return return
def configGet(key: str, *args: str): def configGet(key: str, *args: str, file: str = "config"):
"""Get value of the config key """Get value of the config key
Args: Args:
* key (str): The last key of the keys path. * key (str): The last key of the keys path.
* *args (str): Path to key like: dict[args][key]. * *args (str): Path to key like: dict[args][key].
* file (str): User ID to load. Loads config if not provided. Defaults to "config".
Returns: Returns:
* any: Value of provided key * any: Value of provided key
""" """
if file == "config":
this_dict = jsonLoad("config.json") this_dict = jsonLoad("config.json")
else:
this_dict = jsonLoad(f"data{sep}users{sep}{file}.json")
this_key = this_dict this_key = this_dict
for dict_key in args: for dict_key in args:
this_key = this_key[dict_key] this_key = this_key[dict_key]
return this_key[key] return this_key[key]
# def locale(key: str, *args: str, locale=configGet("locale")): def locale(key: str, *args: str, locale=configGet("locale")) -> Union[str, list, dict]:
# """Get value of locale string """Get value of locale string
# Args: Args:
# * key (str): The last key of the locale's keys path. * key (str): The last key of the locale's keys path.
# * *args (list): Path to key like: dict[args][key]. * *args (list): Path to key like: dict[args][key].
# * locale (str): Locale to looked up in. Defaults to config's locale value. * locale (str): Locale to looked up in. Defaults to config's locale value.
# Returns: Returns:
# * any: Value of provided locale key * any: Value of provided locale key
# """ """
# if (locale == None): if (locale == None):
# locale = configGet("locale") locale = configGet("locale")
# try: try:
# this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{locale}.json') this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{locale}.json')
# except FileNotFoundError: except FileNotFoundError:
# try: try:
# this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{configGet("locale")}.json') this_dict = jsonLoad(f'{configGet("locale", "locations")}{sep}{configGet("locale")}.json')
# except FileNotFoundError: except FileNotFoundError:
# try: return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
# this_dict = jsonLoad(f'{configGet("locale_fallback", "locations")}{sep}{configGet("locale")}.json')
# except:
# return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
# this_key = this_dict this_key = this_dict
# for dict_key in args: for dict_key in args:
# this_key = this_key[dict_key] this_key = this_key[dict_key]
# try: try:
# return this_key[key] return this_key[key]
# except KeyError: except KeyError:
# return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"' return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
try: try:
from psutil import Process from psutil import Process