Compare commits
10 Commits
00a408ac6c
...
v.1.2
Author | SHA1 | Date | |
---|---|---|---|
95be1e72d3 | |||
ecbf7d8b78 | |||
92386ac8ce | |||
dabfa2ecef | |||
234b73add0 | |||
f4fb85f7a4 | |||
4fba305b05 | |||
68c7cc0ada | |||
79304816b0 | |||
2cfa5a8f8d |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -161,4 +161,6 @@ data
|
|||||||
TASK.md
|
TASK.md
|
||||||
inline_bot.py
|
inline_bot.py
|
||||||
.vscode
|
.vscode
|
||||||
migrate.py
|
migrate.py
|
||||||
|
validation/*
|
||||||
|
!validation/*.json
|
@@ -1,5 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from asyncio import sleep
|
from asyncio import sleep
|
||||||
|
from ftfy import fix_text
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
from app import app, isAnAdmin
|
from app import app, isAnAdmin
|
||||||
from typing import Any, List, Literal, Union
|
from typing import Any, List, Literal, Union
|
||||||
@@ -122,6 +123,11 @@ class HoloUser():
|
|||||||
* adm_context (`bool`, *optional*): Whether context sender is an admin. Defaults to False.
|
* 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
|
# Check if any text available and log message sending
|
||||||
if text is not None:
|
if text is not None:
|
||||||
logWrite(f"{context.from_user.id} sent message '{text}' to {self.id} (source message: {context.id})")
|
logWrite(f"{context.from_user.id} sent message '{text}' to {self.id} (source message: {context.id})")
|
||||||
@@ -275,10 +281,9 @@ class HoloUser():
|
|||||||
"""Reset application of a user in tmp collection and replace it with an empty one
|
"""Reset application of a user in tmp collection and replace it with an empty one
|
||||||
"""
|
"""
|
||||||
if col_tmp.find_one({"user": self.id, "type": "application"}) is None:
|
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)
|
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:
|
async def application_next(self, query: str, msg: Message) -> None:
|
||||||
"""Move on filling application of user
|
"""Move on filling application of user
|
||||||
@@ -313,6 +318,9 @@ class HoloUser():
|
|||||||
|
|
||||||
if progress["state"] == "fill" and progress["sent"] is False:
|
if progress["state"] == "fill" and progress["sent"] is False:
|
||||||
|
|
||||||
|
if msg.text is not None:
|
||||||
|
msg.text = fix_text(msg.text)
|
||||||
|
|
||||||
if stage == 2:
|
if stage == 2:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -359,6 +367,9 @@ class HoloUser():
|
|||||||
return
|
return
|
||||||
|
|
||||||
elif stage == 10:
|
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
|
progress["application"][str(stage)] = query
|
||||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "complete": True}})
|
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "complete": True}})
|
||||||
application_content = []
|
application_content = []
|
||||||
@@ -378,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))
|
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:
|
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
|
progress["application"][str(stage)] = query
|
||||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "application"}}, {"$set": {"application": progress["application"], "stage": progress["stage"]+1}})
|
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))))
|
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))))
|
||||||
@@ -430,10 +444,20 @@ class HoloUser():
|
|||||||
|
|
||||||
stage = progress["stage"]
|
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 progress["state"] == "fill" and progress["sent"] is False:
|
||||||
|
|
||||||
if stage == 1:
|
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
|
progress["sponsorship"]["streamer"] = query
|
||||||
col_tmp.update_one({"user": {"$eq": self.id}, "type": {"$eq": "sponsorship"}}, {"$set": {"sponsorship": progress["sponsorship"], "stage": progress["stage"]+1}})
|
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))))
|
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))))
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
"question8": "Чи дивишся ти стріми дівчат Хололайву?",
|
"question8": "Чи дивишся ти стріми дівчат Хололайву?",
|
||||||
"question9": "Чиї пісні з Хололайву тобі подобаються найбільше?",
|
"question9": "Чиї пісні з Хололайву тобі подобаються найбільше?",
|
||||||
"question10": "Ну і нарешті, розкажи трохи про себе. Про хобі, чим тобі подобається займатись. Одним повідомленням, будь ласка.",
|
"question10": "Ну і нарешті, розкажи трохи про себе. Про хобі, чим тобі подобається займатись. Одним повідомленням, будь ласка.",
|
||||||
|
"question_too_long": "Текст занадто довгий. Будь ласка, умісти відповідь у 256 символів.",
|
||||||
"question2_underage": "Вибач, але треба досягти віку {0} років, щоб приєднатись до нас. Такі обмеження існують для того, щоб всім у спільноті було цікаво одне з одним.",
|
"question2_underage": "Вибач, але треба досягти віку {0} років, щоб приєднатись до нас. Такі обмеження існують для того, щоб всім у спільноті було цікаво одне з одним.",
|
||||||
"question2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
"question2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
||||||
"question2_joke": "Шутнік, ми так і поняли. Але будь ласка, введи реальне значення.",
|
"question2_joke": "Шутнік, ми так і поняли. Але будь ласка, введи реальне значення.",
|
||||||
@@ -20,9 +21,11 @@
|
|||||||
"question3_found": "Використовую наступний результат:\n• {0} ({1})",
|
"question3_found": "Використовую наступний результат:\n• {0} ({1})",
|
||||||
"question3_error": "⚠️ **Сталась помилка**\nНе вдалось отримати географічну мітку. Розробника повідомлено про цю помилку. Будь ласка, спробуйте ще раз.",
|
"question3_error": "⚠️ **Сталась помилка**\nНе вдалось отримати географічну мітку. Розробника повідомлено про цю помилку. Будь ласка, спробуйте ще раз.",
|
||||||
"question3_traceback": "⚠️ **Сталась помилка**\nПомилка отримання геокодингу для `{0}`\nПомилка: `{1}`\n\nTraceback:\n```\n{2}\n```",
|
"question3_traceback": "⚠️ **Сталась помилка**\nПомилка отримання геокодингу для `{0}`\nПомилка: `{1}`\n\nTraceback:\n```\n{2}\n```",
|
||||||
|
"question10_too_long": "Текст занадто довгий. Будь ласка, умісти відповідь у 1024 символи.",
|
||||||
"sponsorship_apply": "ℹ️ Оформіть платну підписку на когось з Холо, заповніть форму та отримайте особливу роль в якості винагороди!",
|
"sponsorship_apply": "ℹ️ Оформіть платну підписку на когось з Холо, заповніть форму та отримайте особливу роль в якості винагороди!",
|
||||||
"sponsorship_applying": "ℹ️ Розпочато заповнення форми на отримання бонусів за платну підписку на холодівчат.",
|
"sponsorship_applying": "ℹ️ Розпочато заповнення форми на отримання бонусів за платну підписку на холодівчат.",
|
||||||
"sponsor1": "На яку саме дівчину платна підписка?",
|
"sponsor1": "На яку саме дівчину платна підписка?",
|
||||||
|
"sponsor1_invalid": "Будь ласка, введіть ім'я не довше за 240 символів",
|
||||||
"sponsor2": "До якої дати (`ДД.ММ.РРРР`) підписка?",
|
"sponsor2": "До якої дати (`ДД.ММ.РРРР`) підписка?",
|
||||||
"sponsor2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
"sponsor2_invalid": "Будь ласка, введи дату формату `ДД.ММ.РРРР`",
|
||||||
"sponsor2_past": "Вказана дата знаходиться в минулому. Будь ласка, вкажіть правильний термін дії підписки",
|
"sponsor2_past": "Вказана дата знаходиться в минулому. Будь ласка, вкажіть правильний термін дії підписки",
|
||||||
@@ -108,6 +111,7 @@
|
|||||||
"spoiler_empty": "Спойлер категорії \"{0}\" без опису",
|
"spoiler_empty": "Спойлер категорії \"{0}\" без опису",
|
||||||
"spoiler_described": "Спойлер категорії \"{0}\": {1}",
|
"spoiler_described": "Спойлер категорії \"{0}\": {1}",
|
||||||
"spoiler_description_enter": "Добре, введіть бажаний опис спойлера",
|
"spoiler_description_enter": "Добре, введіть бажаний опис спойлера",
|
||||||
|
"spoiler_description_too_long": "Текст занадто довгий. Будь ласка, умісти опис у 1024 символи.",
|
||||||
"spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)",
|
"spoiler_using_description": "Встановлено опис спойлера: {0}\n\nЗалишилось додати вміст самого спойлера. Бот приймає текстове повідомлення, фото, відео, файл а також гіф зображення (1 шт.)",
|
||||||
"spoiler_send_description": "Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.",
|
"spoiler_send_description": "Тепер треба надіслати коротенький опис спойлера, щоб люди розуміли що під ним варто очкувати. Надішли мінус (-) щоб пропустити цей крок.",
|
||||||
"spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.",
|
"spoiler_ready": "Успіх! Спойлер створено. Користуйтесь кнопкою нижче щоб надіслати його.",
|
||||||
|
@@ -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))
|
await app.send_message(holo_user.id, locale("approved_joined", "message", locale=holo_user))
|
||||||
|
|
||||||
col_applications.delete_one({"user": holo_user.id})
|
applications = col_applications.find({"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"]})
|
|
||||||
|
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}})
|
col_tmp.update_one({"user": holo_user.id, "type": "application"}, {"$set": {"state": "approved", "sent": False}})
|
||||||
|
|
||||||
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
|
||||||
|
@@ -9,7 +9,7 @@ from pyrogram.enums.parse_mode import ParseMode
|
|||||||
from classes.holo_user import HoloUser
|
from classes.holo_user import HoloUser
|
||||||
from modules.utils import all_locales, configGet, locale, logWrite
|
from modules.utils import all_locales, configGet, locale, logWrite
|
||||||
from modules.handlers.welcome import welcome_pass
|
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
|
from modules import custom_filters
|
||||||
|
|
||||||
# Confirmation =================================================================================================================
|
# Confirmation =================================================================================================================
|
||||||
@@ -54,8 +54,12 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
|
|||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
if tmp_application["reapply"]:
|
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(
|
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}")
|
InlineKeyboardButton(text=str(locale("reapply_yes", "button")), callback_data=f"reapply_yes_{holo_user.id}")
|
||||||
@@ -67,7 +71,11 @@ async def confirm_yes(app: Client, msg: Message, kind: Literal["application", "s
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
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}")
|
InlineKeyboardButton(text=str(locale("sub_yes", "button")), callback_data=f"sub_yes_{holo_user.id}")
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
from app import app, isAnAdmin
|
from app import app, isAnAdmin
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from ftfy import fix_text
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.types import Message, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton
|
from pyrogram.types import Message, ForceReply, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
from pyrogram.client import Client
|
from pyrogram.client import Client
|
||||||
@@ -95,8 +96,13 @@ async def any_stage(app: Client, msg: Message):
|
|||||||
# if msg.text == lc[-1][0]:
|
# 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)))
|
# 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
|
# return
|
||||||
|
|
||||||
|
|
||||||
if msg.text != "-":
|
if msg.text != "-":
|
||||||
|
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}} )
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": msg.text}} )
|
||||||
else:
|
else:
|
||||||
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": ""}} )
|
col_spoilers.find_one_and_update( {"user": msg.from_user.id, "completed": False}, {"$set": {"description": ""}} )
|
||||||
|
@@ -13,7 +13,7 @@ for pattern in all_locales("welcome", "keyboard"):
|
|||||||
for pattern in all_locales("return", "keyboard"):
|
for pattern in all_locales("return", "keyboard"):
|
||||||
welcome_1.append(pattern[0][0])
|
welcome_1.append(pattern[0][0])
|
||||||
@app.on_message(custom_filters.enabled_applications & ~filters.scheduled & filters.private & filters.command(welcome_1, prefixes=[""]))
|
@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
|
"""Set user's stage to 1 and start a fresh application
|
||||||
|
|
||||||
### Args:
|
### Args:
|
||||||
@@ -27,7 +27,8 @@ async def welcome_pass(app: Client, msg: Message, once_again: bool = True) -> No
|
|||||||
|
|
||||||
holo_user = HoloUser(msg.from_user)
|
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")
|
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)))
|
await msg.reply_text(locale("question1", "message", locale=msg.from_user), reply_markup=ForceReply(placeholder=locale("question1", "force_reply", locale=msg.from_user)))
|
||||||
|
@@ -2,9 +2,10 @@ APScheduler==3.9.1.post1
|
|||||||
fastapi~=0.88.0
|
fastapi~=0.88.0
|
||||||
psutil==5.9.4
|
psutil==5.9.4
|
||||||
pymongo==4.3.3
|
pymongo==4.3.3
|
||||||
Pyrogram~=2.0.95
|
Pyrogram~=2.0.96
|
||||||
requests==2.28.1
|
requests==2.28.1
|
||||||
tgcrypto==1.2.5
|
tgcrypto==1.2.5
|
||||||
python_dateutil==2.8.2
|
python_dateutil==2.8.2
|
||||||
starlette~=0.22.0
|
starlette~=0.22.0
|
||||||
ujson~=5.7.0
|
ujson~=5.7.0
|
||||||
|
ftfy~=6.1.1
|
Reference in New Issue
Block a user