This commit is contained in:
dj
2023-09-24 13:04:45 +03:00
parent fc98213031
commit edc617bb38
14 changed files with 114 additions and 92 deletions
+7 -3
View File
@@ -21,7 +21,7 @@ colorama.init()
# Запуск шедулеров # Запуск шедулеров
async def scheduler_start(bot): async def scheduler_start(bot):
scheduler.add_job(autobackup_admin, "cron", hour=00, args=(bot,)) # Ежедневный Автобэкап в 00:00 scheduler.add_job(autobackup_admin, "cron", hour=00, args=(bot,)) # Ежедневный Автобэкап в 00:00
scheduler.add_job(autobackup_admin, "cron", hour=12, args=(bot,)) # Ежедневный Автобэкап в 12:00 # scheduler.add_job(autobackup_admin, "cron", hour=12, args=(bot,)) # Ежедневный Автобэкап в 12:00
# Запуск бота и функций # Запуск бота и функций
@@ -39,7 +39,7 @@ async def main():
await startup_notify(bot) await startup_notify(bot)
await scheduler_start(bot) await scheduler_start(bot)
bot_logger.warning("Bot was started") bot_logger.warning("BOT WAS STARTED")
print(colorama.Fore.LIGHTYELLOW_EX + f"~~~~~ Bot was started - @{(await bot.get_me()).username} ~~~~~") print(colorama.Fore.LIGHTYELLOW_EX + f"~~~~~ Bot was started - @{(await bot.get_me()).username} ~~~~~")
print(colorama.Fore.LIGHTBLUE_EX + "~~~~~ TG developer - @djimbox ~~~~~") print(colorama.Fore.LIGHTBLUE_EX + "~~~~~ TG developer - @djimbox ~~~~~")
print(colorama.Fore.RESET) print(colorama.Fore.RESET)
@@ -49,7 +49,11 @@ async def main():
await bot.delete_webhook() await bot.delete_webhook()
await bot.get_updates(offset=-1) await bot.get_updates(offset=-1)
await dp.start_polling(bot, allowed_updates=dp.resolve_used_update_types(), rSession=rSession) await dp.start_polling(
bot,
allowed_updates=dp.resolve_used_update_types(),
rSession=rSession,
)
finally: finally:
await rSession.close() await rSession.close()
await bot.session.close() await bot.session.close()
+8 -7
View File
@@ -1,7 +1,8 @@
APScheduler==3.9.1 APScheduler~=3.9.1
aiogram==3.0.0b7 aiogram~=3.0.0
colorlog==6.7.0 colorlog~=6.7.0
typing==3.7.4.3 pytz~=2022.6
aiohttp==3.8.4 typing~=3.7.4.3
colorama==0.4.5 aiohttp~=3.8.5
cachetools==5.3.0 cachetools~=4.2.4
colorama~=0.4.5
+1 -1
View File
@@ -15,7 +15,7 @@ PATH_LOGS = "tgbot/data/logs.log" # Путь к Логам
# Образы и конфиги # Образы и конфиги
scheduler = AsyncIOScheduler(timezone=BOT_TIMEZONE) # Образ шедулера scheduler = AsyncIOScheduler(timezone=BOT_TIMEZONE) # Образ шедулера
start_status = True # Оповещение админам при запуске бота (True или False) start_status = True # Оповещение админам о запуске бота (True или False)
# Получение администраторов бота # Получение администраторов бота
+7 -6
View File
@@ -8,18 +8,19 @@ from tgbot.utils.const_functions import ikb
# Кнопки инлайн меню # Кнопки инлайн меню
def menu_finl(user_id) -> InlineKeyboardMarkup: def menu_finl(user_id) -> InlineKeyboardMarkup:
keyboard = InlineKeyboardBuilder( keyboard = InlineKeyboardBuilder()
).row(
keyboard.row(
ikb("User X", data="user_inline_x"), ikb("User X", data="user_inline_x"),
ikb("User 1", data="user_inline:1"), ikb("User 1", data="user_inline:user_btn"),
ikb("User 2", data="user_inline:2"), ikb("User 2", data="..."),
) )
if user_id in get_admins(): if user_id in get_admins():
keyboard.row( keyboard.row(
ikb("Admin X", data="admin_inline_x"), ikb("Admin X", data="admin_inline_x"),
ikb("Admin 1", data="admin_inline:1"), ikb("Admin 1", data="admin_inline:admin_btn"),
ikb("Admin 2", data="admin_inline:2"), ikb("Admin 2", data="unknown"),
) )
return keyboard.as_markup() return keyboard.as_markup()
+2 -2
View File
@@ -9,7 +9,7 @@ admin_rep = ReplyKeyboardBuilder(
rkb("Admin Reply 1"), rkb("Admin Reply 1"),
rkb("Admin Reply 2"), rkb("Admin Reply 2"),
).row( ).row(
rkb("🔙 Главное меню"), rkb("🔙 Main menu"),
).as_markup(resize_keyboard=True) ).as_markup(resize_keyboard=True)
# Тестовые юзер реплай кнопки # Тестовые юзер реплай кнопки
@@ -18,5 +18,5 @@ user_rep = ReplyKeyboardBuilder(
rkb("User Reply 1"), rkb("User Reply 1"),
rkb("User Reply 2"), rkb("User Reply 2"),
).row( ).row(
rkb("🔙 Главное меню"), rkb("🔙 Main menu"),
).as_markup(resize_keyboard=True) ).as_markup(resize_keyboard=True)
+8 -4
View File
@@ -46,11 +46,15 @@ class ThrottlingMiddleware(BaseMiddleware):
self.users[this_user.id]['count_throttled'] = 2 self.users[this_user.id]['count_throttled'] = 2
self.users[this_user.id]['now_rate'] = self.default_rate + 3 self.users[this_user.id]['now_rate'] = self.default_rate + 3
await event.reply("<b>❗ Пожалуйста, не спамьте.\n" await event.reply(
"❗ Please, do not spam.</b>") "<b>❗ Пожалуйста, не спамьте.\n"
"❗ Please, do not spam.</b>",
)
elif self.users[this_user.id]['count_throttled'] == 2: elif self.users[this_user.id]['count_throttled'] == 2:
self.users[this_user.id]['count_throttled'] = 3 self.users[this_user.id]['count_throttled'] = 3
self.users[this_user.id]['now_rate'] = self.default_rate + 5 self.users[this_user.id]['now_rate'] = self.default_rate + 5
await event.reply("<b>❗ Бот не будет отвечать до прекращения спама.\n" await event.reply(
"❗ The bot will not respond until the spam stops.</b>") "<b>❗ Бот не будет отвечать до прекращения спама.\n"
"❗ The bot will not respond until the spam stops.</b>",
)
+6 -6
View File
@@ -1,6 +1,6 @@
# - *- coding: utf- 8 - *- # - *- coding: utf- 8 - *-
from aiogram import Router, Bot from aiogram import Router, Bot, F
from aiogram.filters import Text, Command from aiogram.filters import Command
from aiogram.types import FSInputFile, Message, CallbackQuery from aiogram.types import FSInputFile, Message, CallbackQuery
from tgbot.data.config import PATH_DATABASE, PATH_LOGS from tgbot.data.config import PATH_DATABASE, PATH_LOGS
@@ -13,7 +13,7 @@ router = Router()
# Кнопка - Admin Inline # Кнопка - Admin Inline
@router.message(Text(text="Admin Inline")) @router.message(F.text == 'Admin Inline')
async def admin_button_inline(message: Message, bot: Bot, state: FSM, rSession: RS, my_user): async def admin_button_inline(message: Message, bot: Bot, state: FSM, rSession: RS, my_user):
await state.clear() await state.clear()
@@ -21,7 +21,7 @@ async def admin_button_inline(message: Message, bot: Bot, state: FSM, rSession:
# Кнопка - Admin Reply # Кнопка - Admin Reply
@router.message(Text(text="Admin Reply")) @router.message(F.text == 'Admin Reply')
async def admin_button_reply(message: Message, bot: Bot, state: FSM, rSession: RS, my_user): async def admin_button_reply(message: Message, bot: Bot, state: FSM, rSession: RS, my_user):
await state.clear() await state.clear()
@@ -29,13 +29,13 @@ async def admin_button_reply(message: Message, bot: Bot, state: FSM, rSession: R
# Колбэк - Admin X # Колбэк - Admin X
@router.callback_query(Text(text="admin_inline_x")) @router.callback_query(F.data == 'admin_inline_x')
async def admin_callback_inline_x(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user): async def admin_callback_inline_x(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user):
await call.answer(f"Click Admin X") await call.answer(f"Click Admin X")
# Колбэк - Admin # Колбэк - Admin
@router.callback_query(Text(startswith="admin_inline:")) @router.callback_query(F.data.startswith('admin_inline:'))
async def admin_callback_inline(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user): async def admin_callback_inline(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user):
get_data = call.data.split(":")[1] get_data = call.data.split(":")[1]
+10 -18
View File
@@ -1,22 +1,21 @@
# - *- coding: utf- 8 - *- # - *- coding: utf- 8 - *-
from aiogram import Router, Bot from aiogram import Router, Bot, F
from aiogram.filters import Text
from aiogram.types import CallbackQuery, Message from aiogram.types import CallbackQuery, Message
from tgbot.keyboards.reply_main import menu_frep from tgbot.utils.const_functions import del_message
from tgbot.utils.misc.bot_models import FSM, RS from tgbot.utils.misc.bot_models import FSM, RS
router = Router() router = Router()
# Колбэк с удалением сообщения # Колбэк с удалением сообщения
@router.callback_query(Text(text="close_this")) @router.callback_query(F.data == 'close_this')
async def main_callback_close(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user): async def main_callback_close(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user):
await call.message.delete() await del_message(call.message)
# Колбэк с обработкой кнопки # Колбэк с обработкой кнопки
@router.callback_query(Text(text="...")) @router.callback_query(F.data == '...')
async def main_callback_answer(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user): async def main_callback_answer(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user):
await call.answer(cache_time=30) await call.answer(cache_time=30)
@@ -24,20 +23,13 @@ async def main_callback_answer(call: CallbackQuery, bot: Bot, state: FSM, rSessi
# Колбэк с обработкой удаления сообщений потерявших стейт # Колбэк с обработкой удаления сообщений потерявших стейт
@router.callback_query() @router.callback_query()
async def main_callback_missed(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user): async def main_callback_missed(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user):
try: await call.answer(f"❗️ Miss callback: {call.data}", True)
await call.message.delete()
except:
pass
await call.message.answer(
"❌ Данные не были найдены из-за перезапуска скрипта.\n"
"♻ Выполните действие заново.",
reply_markup=menu_frep(call.from_user.id),
)
# Обработка всех неизвестных команд # Обработка всех неизвестных команд
@router.message() @router.message()
async def main_message_missed(message: Message, bot: Bot, state: FSM, rSession: RS, my_user): async def main_message_missed(message: Message, bot: Bot, state: FSM, rSession: RS, my_user):
await message.answer("♦ Неизвестная команда.\n" await message.answer(
"♦ Введите /start") "♦️ Unknown command.\n"
"♦️ Enter /start",
)
+6 -7
View File
@@ -1,6 +1,6 @@
# - *- coding: utf- 8 - *- # - *- coding: utf- 8 - *-
from aiogram import Router, Bot from aiogram import Router, Bot, F
from aiogram.filters import Text, Command from aiogram.filters import Command
from aiogram.types import Message from aiogram.types import Message
from tgbot.keyboards.reply_main import menu_frep from tgbot.keyboards.reply_main import menu_frep
@@ -11,16 +11,15 @@ router = Router()
# Открытие главного меню # Открытие главного меню
@router.message(Text(text=['🔙 Главное меню'])) @router.message(F.text.in_(('🔙 Main menu', '🔙 Return')))
@router.message(Command(commands=['start'])) @router.message(Command(commands=['start']))
async def main_start(message: Message, bot: Bot, state: FSM, rSession: RS, my_user): async def main_start(message: Message, bot: Bot, state: FSM, rSession: RS, my_user):
await state.clear() await state.clear()
await message.answer( await message.answer(
ded(""" ded(f"""
🔸 Бот готов к использованию. 🔸 Hello, {my_user['user_name']}
🔸 Если не появились вспомогательные кнопки 🔸 Enter /start or /inline
🔸 Введите /start
"""), """),
reply_markup=menu_frep(message.from_user.id), reply_markup=menu_frep(message.from_user.id),
) )
+18 -9
View File
@@ -1,6 +1,6 @@
# - *- coding: utf- 8 - *- # - *- coding: utf- 8 - *-
from aiogram import Router, Bot from aiogram import Router, Bot, F
from aiogram.filters import Command, Text from aiogram.filters import Command
from aiogram.types import Message, CallbackQuery from aiogram.types import Message, CallbackQuery
from tgbot.keyboards.inline_main import menu_finl from tgbot.keyboards.inline_main import menu_finl
@@ -12,19 +12,25 @@ router = Router()
# Кнопка - User Inline # Кнопка - User Inline
@router.message(Text(text="User Inline")) @router.message(F.text == 'User Inline')
async def user_button_inline(message: Message, bot: Bot, state: FSM, rSession: RS, my_user): async def user_button_inline(message: Message, bot: Bot, state: FSM, rSession: RS, my_user):
await state.clear() await state.clear()
await message.answer("Click Button - User Inline", reply_markup=user_inl) await message.answer(
"Click Button - User Inline",
reply_markup=user_inl,
)
# Кнопка - User Reply # Кнопка - User Reply
@router.message(Text(text="User Reply")) @router.message(F.text == 'User Reply')
async def user_button_reply(message: Message, bot: Bot, state: FSM, rSession: RS, my_user): async def user_button_reply(message: Message, bot: Bot, state: FSM, rSession: RS, my_user):
await state.clear() await state.clear()
await message.answer("Click Button - User Reply", reply_markup=user_rep) await message.answer(
"Click Button - User Reply",
reply_markup=user_rep,
)
# Команда - /inline # Команда - /inline
@@ -32,17 +38,20 @@ async def user_button_reply(message: Message, bot: Bot, state: FSM, rSession: RS
async def user_command_inline(message: Message, bot: Bot, state: FSM, rSession: RS, my_user): async def user_command_inline(message: Message, bot: Bot, state: FSM, rSession: RS, my_user):
await state.clear() await state.clear()
await message.answer("Click command - /inline", reply_markup=menu_finl(message.from_user.id)) await message.answer(
"Click command - /inline",
reply_markup=menu_finl(message.from_user.id),
)
# Колбэк - User X # Колбэк - User X
@router.callback_query(Text(text="user_inline_x")) @router.callback_query(F.data == 'user_inline_x')
async def user_callback_inline_x(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user): async def user_callback_inline_x(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user):
await call.answer(f"Click User X") await call.answer(f"Click User X")
# Колбэк - User # Колбэк - User
@router.callback_query(Text(startswith="user_inline:")) @router.callback_query(F.data.startswith('user_inline:'))
async def user_callback_inline(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user): async def user_callback_inline(call: CallbackQuery, bot: Bot, state: FSM, rSession: RS, my_user):
get_data = call.data.split(":")[1] get_data = call.data.split(":")[1]
+24 -20
View File
@@ -2,11 +2,11 @@
import sqlite3 import sqlite3
from tgbot.data.config import PATH_DATABASE from tgbot.data.config import PATH_DATABASE
from tgbot.utils.const_functions import get_unix, get_date from tgbot.utils.const_functions import get_unix
# Преобразование БД словаря # Преобразование БД словаря
def dict_factory(cursor, row): def dict_factory(cursor, row) -> dict:
this_dict = {} this_dict = {}
for idx, col in enumerate(cursor.description): for idx, col in enumerate(cursor.description):
@@ -18,7 +18,7 @@ def dict_factory(cursor, row):
#################################################################################################### ####################################################################################################
##################################### ФОРМАТИРОВАНИЕ ЗАПРОСОВ ###################################### ##################################### ФОРМАТИРОВАНИЕ ЗАПРОСОВ ######################################
# Форматирование запроса без аргументов # Форматирование запроса без аргументов
def update_format(sql, parameters: dict): def update_format(sql, parameters: dict) -> tuple[str, list]:
values = ", ".join([ values = ", ".join([
f"{item} = ?" for item in parameters f"{item} = ?" for item in parameters
]) ])
@@ -28,7 +28,7 @@ def update_format(sql, parameters: dict):
# Форматирование запроса с аргументами # Форматирование запроса с аргументами
def update_format_where(sql, parameters: dict): def update_format_args(sql, parameters: dict) -> tuple[str, list]:
sql += " WHERE " sql += " WHERE "
sql += " AND ".join([ sql += " AND ".join([
@@ -44,10 +44,12 @@ def update_format_where(sql, parameters: dict):
def add_userx(user_id, user_login, user_name, user_surname, user_fullname): def add_userx(user_id, user_login, user_name, user_surname, user_fullname):
with sqlite3.connect(PATH_DATABASE) as con: with sqlite3.connect(PATH_DATABASE) as con:
con.row_factory = dict_factory con.row_factory = dict_factory
con.execute("INSERT INTO storage_users " con.execute(
"(user_id, user_login, user_name, user_surname, user_fullname, user_unix) " "INSERT INTO storage_users "
"VALUES (?, ?, ?, ?, ?, ?)", "(user_id, user_login, user_name, user_surname, user_fullname, user_unix) "
[user_id, user_login, user_name, user_surname, user_fullname, get_unix()]) "VALUES (?, ?, ?, ?, ?, ?)",
[user_id, user_login, user_name, user_surname, user_fullname, get_unix()],
)
# Получение пользователя # Получение пользователя
@@ -55,7 +57,7 @@ def get_userx(**kwargs):
with sqlite3.connect(PATH_DATABASE) as con: with sqlite3.connect(PATH_DATABASE) as con:
con.row_factory = dict_factory con.row_factory = dict_factory
sql = "SELECT * FROM storage_users" sql = "SELECT * FROM storage_users"
sql, parameters = update_format_where(sql, kwargs) sql, parameters = update_format_args(sql, kwargs)
return con.execute(sql, parameters).fetchone() return con.execute(sql, parameters).fetchone()
@@ -64,7 +66,7 @@ def get_usersx(**kwargs):
with sqlite3.connect(PATH_DATABASE) as con: with sqlite3.connect(PATH_DATABASE) as con:
con.row_factory = dict_factory con.row_factory = dict_factory
sql = "SELECT * FROM storage_users" sql = "SELECT * FROM storage_users"
sql, parameters = update_format_where(sql, kwargs) sql, parameters = update_format_args(sql, kwargs)
return con.execute(sql, parameters).fetchall() return con.execute(sql, parameters).fetchall()
@@ -91,7 +93,7 @@ def delete_userx(**kwargs):
with sqlite3.connect(PATH_DATABASE) as con: with sqlite3.connect(PATH_DATABASE) as con:
con.row_factory = dict_factory con.row_factory = dict_factory
sql = "DELETE FROM storage_users" sql = "DELETE FROM storage_users"
sql, parameters = update_format_where(sql, kwargs) sql, parameters = update_format_args(sql, kwargs)
con.execute(sql, parameters) con.execute(sql, parameters)
@@ -105,13 +107,15 @@ def create_dbx():
if len(con.execute("PRAGMA table_info(storage_users)").fetchall()) == 7: if len(con.execute("PRAGMA table_info(storage_users)").fetchall()) == 7:
print("DB was found(1/1)") print("DB was found(1/1)")
else: else:
con.execute("CREATE TABLE storage_users(" con.execute(
"increment INTEGER PRIMARY KEY AUTOINCREMENT, " "CREATE TABLE storage_users("
"user_id INTEGER," "increment INTEGER PRIMARY KEY AUTOINCREMENT, "
"user_login TEXT," "user_id INTEGER,"
"user_name TEXT," "user_login TEXT,"
"user_surname TEXT," "user_name TEXT,"
"user_fullname TEXT," "user_surname TEXT,"
"user_unix INTEGER" "user_fullname TEXT,"
")") "user_unix INTEGER"
")"
)
print("DB was not found(1/1) | Creating...") print("DB was not found(1/1) | Creating...")
+10 -2
View File
@@ -6,7 +6,7 @@ from typing import Union
import pytz import pytz
from aiogram import Bot, types from aiogram import Bot, types
from aiogram.types import InlineKeyboardButton, KeyboardButton, WebAppInfo from aiogram.types import InlineKeyboardButton, KeyboardButton, WebAppInfo, Message
from tgbot.data.config import get_admins, BOT_TIMEZONE from tgbot.data.config import get_admins, BOT_TIMEZONE
@@ -29,6 +29,14 @@ def ikb(text: str, data: str = None, url: str = None, switch: str = None, web: s
return InlineKeyboardButton(text=text, web_app=WebAppInfo(url=web)) return InlineKeyboardButton(text=text, web_app=WebAppInfo(url=web))
# Удаление сообщений с обработкой ошибки от телеграма
async def del_message(message: Message):
try:
await message.delete()
except:
...
# Отправка сообщения всем админам # Отправка сообщения всем админам
async def send_admins(bot: Bot, text: str, markup=None, not_me=0): async def send_admins(bot: Bot, text: str, markup=None, not_me=0):
for admin in get_admins(): for admin in get_admins():
@@ -36,7 +44,7 @@ async def send_admins(bot: Bot, text: str, markup=None, not_me=0):
if str(admin) != str(not_me): if str(admin) != str(not_me):
await bot.send_message(admin, text, reply_markup=markup, disable_web_page_preview=True) await bot.send_message(admin, text, reply_markup=markup, disable_web_page_preview=True)
except: except:
pass ...
# Умная отправка сообщений # Умная отправка сообщений
+6 -6
View File
@@ -6,16 +6,16 @@ from tgbot.data.config import get_admins
# Команды для юзеров # Команды для юзеров
user_commands = [ user_commands = [
BotCommand(command="start", description=" Перезапустить бота"), BotCommand(command="start", description=" Restart bot"),
BotCommand(command="inline", description="🌀 Получить Inline клавиатуру"), BotCommand(command="inline", description="🌀 Get Inline keyboard"),
] ]
# Команды для админов # Команды для админов
admin_commands = [ admin_commands = [
BotCommand(command="start", description=" Перезапустить бота"), BotCommand(command="start", description=" Restart bot"),
BotCommand(command="inline", description="🌀 Получить Inline клавиатуру"), BotCommand(command="inline", description="🌀 Get Inline keyboard"),
BotCommand(command="log", description="🖨 Получить Логи"), BotCommand(command="log", description="🖨 Get Logs"),
BotCommand(command="db", description="📦 Получить Базу Данных"), BotCommand(command="db", description="📦 Get Database"),
] ]
+1 -1
View File
@@ -9,7 +9,7 @@ from tgbot.utils.const_functions import get_date, send_admins
# Выполнение функции после запуска бота (рассылка админам о запуске бота) # Выполнение функции после запуска бота (рассылка админам о запуске бота)
async def startup_notify(bot: Bot): async def startup_notify(bot: Bot):
if len(get_admins()) >= 1 and start_status: if len(get_admins()) >= 1 and start_status:
await send_admins(bot, "<b>✅ Бот был запущен</b>") await send_admins(bot, "<b>✅ Bot was started</b>")
# Автоматические бэкапы БД # Автоматические бэкапы БД