This commit is contained in:
djimbo
2022-11-18 14:29:52 +03:00
parent 9ba4ee7215
commit 7d4aaf99d0
14 changed files with 185 additions and 109 deletions
+5 -6
View File
@@ -13,15 +13,15 @@ from tgbot.services.api_session import AsyncSession
from tgbot.services.api_sqlite import create_dbx
from tgbot.utils.misc.bot_commands import set_commands
from tgbot.utils.misc.bot_logging import bot_logger
from tgbot.utils.misc_functions import autobackup, startup_notify
from tgbot.utils.misc_functions import autobackup_admin, startup_notify
colorama.init()
# Запуск шедулеров
async def scheduler_start(bot):
scheduler.add_job(autobackup, "cron", hour=00, args=(bot,)) # Ежедневный Автобэкап в 00:00
scheduler.add_job(autobackup, "cron", hour=12, args=(bot,)) # Ежедневный Автобэкап в 12: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
# Запуск бота и функций
@@ -38,11 +38,10 @@ async def main():
await set_commands(bot)
await startup_notify(bot)
await scheduler_start(bot)
bot_info = await bot.get_me()
bot_logger.warning("Bot was started")
print(colorama.Fore.LIGHTYELLOW_EX + f"~~~~~ Bot was started - @{bot_info.username} ~~~~~")
print(colorama.Fore.LIGHTBLUE_EX + "~~~~~ TG developer: @djimbox ~~~~~")
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.RESET)
if len(get_admins()) == 0: print("***** ENTER ADMIN ID IN settings.ini *****")
+4 -4
View File
@@ -1,6 +1,6 @@
APScheduler==3.9.1
aiogram==3.0.0b5
colorlog==6.7.0
aiogram>=3.0.0b4
aiohttp==3.8.1
typing==3.7.4.3
APScheduler==3.8.0
colorama==0.4.5
aiohttp==3.8.3
colorama==0.4.5
+4 -4
View File
@@ -4,7 +4,7 @@ import configparser
from apscheduler.schedulers.asyncio import AsyncIOScheduler
# Токен бота
BOT_TOKEN = configparser.ConfigParser(timezone="Europe/Moscow")
BOT_TOKEN = configparser.ConfigParser()
BOT_TOKEN.read("settings.ini")
BOT_TOKEN = BOT_TOKEN['settings']['token'].strip().replace(' ', '')
@@ -22,10 +22,10 @@ def get_admins():
read_admins = configparser.ConfigParser()
read_admins.read('settings.ini')
admins = read_admins['settings']['admin_id'].strip().replace(' ', '')
admins = read_admins['settings']['admin_id'].strip().replace(" ", "")
if ',' in admins:
admins = admins.split(',')
if "," in admins:
admins = admins.split(",")
else:
if len(admins) >= 1:
admins = [admins]
+6 -4
View File
@@ -9,14 +9,16 @@ from tgbot.utils.const_functions import ikb
def menu_finl(user_id):
keyboard = InlineKeyboardBuilder(
).row(
ikb("User 1", data="..."),
ikb("User 2", data="..."),
ikb("User X", data="user_inline_x"),
ikb("User 1", data="user_inline:1"),
ikb("User 2", data="user_inline:2"),
)
if user_id in get_admins():
keyboard.row(
ikb("Admin 1", data="..."),
ikb("Admin 2", data="..."),
ikb("Admin X", data="admin_inline_x"),
ikb("Admin 1", data="admin_inline:1"),
ikb("Admin 2", data="admin_inline:2"),
)
return keyboard.as_markup()
+2 -2
View File
@@ -9,7 +9,7 @@ admin_rep = ReplyKeyboardBuilder(
rkb("Admin Reply 1"),
rkb("Admin Reply 2"),
).row(
rkb(" Главное меню"),
rkb("🔙 Главное меню"),
).as_markup(resize_keyboard=True)
# Тестовые юзер реплай кнопки
@@ -18,5 +18,5 @@ user_rep = ReplyKeyboardBuilder(
rkb("User Reply 1"),
rkb("User Reply 2"),
).row(
rkb(" Главное меню"),
rkb("🔙 Главное меню"),
).as_markup(resize_keyboard=True)
+1 -1
View File
@@ -22,7 +22,7 @@ def register_all_routers(dp: Dispatcher):
dp.include_router(main_errors.router)
dp.include_router(main_start.router)
# Подключение хендлеров (юзеров и админов)
# Подключение пользовательских роутеров (юзеров и админов)
dp.include_router(user_menu.router) # Юзер хендлер
dp.include_router(admin_menu.router) # Админ хендлер
+26 -10
View File
@@ -1,6 +1,7 @@
# - *- coding: utf- 8 - *-
from aiogram import Router, Bot
from aiogram.types import FSInputFile, Message
from aiogram.filters import Text, Command
from aiogram.types import FSInputFile, Message, CallbackQuery
from tgbot.data.config import PATH_DATABASE, PATH_LOGS
from tgbot.keyboards.inline_misc import admin_inl
@@ -12,7 +13,7 @@ router = Router()
# Кнопка - Admin Inline
@router.message(text="Admin Inline")
@router.message(Text(text="Admin Inline"))
async def admin_button_inline(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
@@ -20,35 +21,50 @@ async def admin_button_inline(message: Message, bot: Bot, state: FSM, aSession:
# Кнопка - Admin Reply
@router.message(text="Admin Reply")
@router.message(Text(text="Admin Reply"))
async def admin_button_reply(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
await message.answer("Click Button - Admin Reply", reply_markup=admin_rep)
# Колбэк - Admin X
@router.callback_query(Text(text="admin_inline_x"))
async def admin_callback_inline_x(call: CallbackQuery, bot: Bot, state: FSM, aSession: AS, my_user):
await call.answer(f"Click Admin X")
# Колбэк - Admin
@router.callback_query(Text(startswith="admin_inline:"))
async def admin_callback_inline(call: CallbackQuery, bot: Bot, state: FSM, aSession: AS, my_user):
get_data = call.data.split(":")[1]
await call.answer(f"Click Admin - {get_data}", True)
# Получение Базы Данных
@router.message(commands=['db', 'database'])
@router.message(Command(commands=['db', 'database']))
async def admin_database(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
await message.answer_document(FSInputFile(PATH_DATABASE),
caption=f"<b>📦 BACKUP</b>\n"
f"<code>🕰 {get_date()}</code>")
f"🕰 <code>{get_date()}</code>")
# Получение логов
@router.message(commands=['log', 'logs'])
@router.message(Command(commands=['log', 'logs']))
async def admin_log(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
await message.answer_document(FSInputFile(PATH_LOGS), caption=f"<code>🕰 {get_date()}</code>")
await message.answer_document(FSInputFile(PATH_LOGS),
caption=f"<b>🖨 LOGS</b>\n"
f"🕰 <code>{get_date()}</code>")
# Очистить логи
@router.message(text_contains=['log', '_', 'clean'])
@router.message(text_contains=['log', '_', 'clear'])
async def admin_log_clear(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
@router.message(Command(commands=['clear_log', 'clear_logs', 'log_clear', 'logs_clear']))
async def admin_logs_clear(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
with open(PATH_LOGS, "w") as file:
+21 -18
View File
@@ -1,26 +1,29 @@
# - *- coding: utf- 8 - *-
from aiogram import Router, Bot
from aiogram.exceptions import TelegramAPIError
from aiogram.types import Update
from aiogram import Router
from aiogram.exceptions import TelegramForbiddenError
from aiogram.filters import ExceptionTypeFilter, ExceptionMessageFilter
from aiogram.handlers import ErrorHandler
from tgbot.utils.misc.bot_logging import bot_logger
from tgbot.utils.misc_functions import send_admins
router = Router()
# Обработка ошибок
@router.errors()
async def processing_errors(update: Update, exception: TelegramAPIError, bot: Bot):
print(f"-Exception | {exception}")
await send_admins(
bot,
f"<b>❌ Ошибка\n\n"
f"<b>Exception: <code>{exception}</code>\n\n"
f"Update: <code>{update.dict()}</code></b>"
)
# Ошибка с блокировкой бота пользователем
@router.errors(ExceptionTypeFilter(TelegramForbiddenError))
class MyHandler(ErrorHandler):
async def handle(self):
pass
bot_logger.exception(
f"Exception: {exception}\n"
f"Update: {update.dict()}"
)
# Ошибка с редактированием одинакового сообщения
@router.errors(ExceptionMessageFilter(
"Bad Request: message is not modified: specified new message content and reply markup are exactly the same as a current content and reply markup of the message"))
class MyHandler(ErrorHandler):
async def handle(self):
bot_logger.exception(
f"====================\n"
f"Exception name: {self.exception_name}\n"
f"Exception message: {self.exception_message}\n"
f"===================="
)
+10 -9
View File
@@ -1,28 +1,29 @@
# - *- coding: utf- 8 - *-
from aiogram import types, Router
from aiogram.types import CallbackQuery
from aiogram import Router, Bot
from aiogram.filters import Text
from aiogram.types import CallbackQuery, Message
from tgbot.keyboards.reply_main import menu_frep
from tgbot.utils.misc.bot_models import FSM
from tgbot.utils.misc.bot_models import FSM, AS
router = Router()
# Колбэк с удалением сообщения
@router.callback_query(text="close_this")
async def processing_callback_close(call: CallbackQuery, state: FSM):
@router.callback_query(Text(text="close_this"))
async def main_callback_close(call: CallbackQuery, bot: Bot, state: FSM, aSession: AS, my_user):
await call.message.delete()
# Колбэк с обработкой кнопки
@router.callback_query(text="...")
async def processing_callback_answer(call: CallbackQuery, state: FSM):
@router.callback_query(Text(text="..."))
async def main_callback_answer(call: CallbackQuery, bot: Bot, state: FSM, aSession: AS, my_user):
await call.answer(cache_time=20)
# Колбэк с обработкой удаления сообщений потерявших стейт
@router.callback_query()
async def processing_callback_missed(call: CallbackQuery, state: FSM):
async def main_callback_missed(call: CallbackQuery, bot: Bot, state: FSM, aSession: AS, my_user):
try:
await call.message.delete()
except:
@@ -35,6 +36,6 @@ async def processing_callback_missed(call: CallbackQuery, state: FSM):
# Обработка всех неизвестных команд
@router.message()
async def processing_message_missed(message: types.Message, state: FSM):
async def main_message_missed(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await message.answer("♦ Неизвестная команда.\n"
"▶ Введите /start")
+3 -1
View File
@@ -1,5 +1,6 @@
# - *- coding: utf- 8 - *-
from aiogram import Router, Bot
from aiogram.filters import Text, Command
from aiogram.types import Message
from tgbot.keyboards.reply_main import menu_frep
@@ -9,7 +10,8 @@ router = Router()
# Открытие главного меню
@router.message(text_startswith=[" Главное меню", "/start"])
@router.message(Text(text=['🔙 Главное меню']))
@router.message(Command(commands=['start']))
async def main_start(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
+19 -4
View File
@@ -1,6 +1,7 @@
# - *- coding: utf- 8 - *-
from aiogram import Router, Bot
from aiogram.types import Message
from aiogram.filters import Command, Text
from aiogram.types import Message, CallbackQuery
from tgbot.keyboards.inline_main import menu_finl
from tgbot.keyboards.inline_misc import user_inl
@@ -11,7 +12,7 @@ router = Router()
# Кнопка - User Inline
@router.message(text="User Inline")
@router.message(Text(text="User Inline"))
async def user_button_inline(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
@@ -19,7 +20,7 @@ async def user_button_inline(message: Message, bot: Bot, state: FSM, aSession: A
# Кнопка - User Reply
@router.message(text="User Reply")
@router.message(Text(text="User Reply"))
async def user_button_reply(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
@@ -27,8 +28,22 @@ async def user_button_reply(message: Message, bot: Bot, state: FSM, aSession: AS
# Команда - /inline
@router.message(commands="inline")
@router.message(Command(commands="inline"))
async def user_command_inline(message: Message, bot: Bot, state: FSM, aSession: AS, my_user):
await state.clear()
await message.answer("Click command - /inline", reply_markup=menu_finl(message.from_user.id))
# Колбэк - User X
@router.callback_query(Text(text="user_inline_x"))
async def user_callback_inline_x(call: CallbackQuery, bot: Bot, state: FSM, aSession: AS, my_user):
await call.answer(f"Click User X")
# Колбэк - User
@router.callback_query(Text(startswith="user_inline:"))
async def user_callback_inline(call: CallbackQuery, bot: Bot, state: FSM, aSession: AS, my_user):
get_data = call.data.split(":")[1]
await call.answer(f"Click User - {get_data}", True)
+2 -1
View File
@@ -116,5 +116,6 @@ def create_dbx():
"user_surname TEXT,"
"user_fullname TEXT,"
"user_date TIMESTAMP,"
"user_unix INTEGER)")
"user_unix INTEGER"
")")
print("DB was not found(1/1) | Creating...")
+80 -43
View File
@@ -2,20 +2,22 @@
import random
import time
from datetime import datetime
from typing import Union
from aiogram import Bot, types
from aiogram.types import InlineKeyboardButton, KeyboardButton
from tgbot.data.config import get_admins
######################################## AIOGRAM ########################################
# Генерация реплай кнопки
def rkb(text):
def rkb(text) -> KeyboardButton:
return KeyboardButton(text=text)
# Генерация инлайн кнопки
def ikb(text, data=None, url=None, switch=None):
def ikb(text, data=None, url=None, switch=None) -> InlineKeyboardButton:
if data is not None:
return InlineKeyboardButton(text=text, callback_data=data)
elif url is not None:
@@ -71,7 +73,7 @@ async def smart_send(bot: Bot, message: types.Message, user_id, text_add=None, r
######################################## ПРОЧЕЕ ########################################
# Удаление отступов у текста
def ded(get_text: str):
def ded(get_text: str) -> str:
if get_text is not None:
split_text = get_text.split("\n")
if split_text[0] == "": split_text.pop(0)
@@ -84,20 +86,25 @@ def ded(get_text: str):
save_text.append(text)
get_text = "\n".join(save_text)
else:
get_text = ""
return get_text
# Очистка HTML тэгов
def clear_html(get_text: str):
def clear_html(get_text: str) -> str:
if get_text is not None:
if "<" in get_text: get_text = get_text.replace("<", "*")
if ">" in get_text: get_text = get_text.replace(">", "*")
else:
get_text = ""
return get_text
# Очистка пробелов в списке
def clear_list(get_list: list):
def clear_list(get_list: list) -> list:
while "" in get_list: get_list.remove("")
while " " in get_list: get_list.remove(" ")
while "," in get_list: get_list.remove(",")
@@ -112,7 +119,7 @@ def split_messages(get_list: list, count: int):
# Получение даты
def get_date():
def get_date() -> str:
this_date = datetime.today().replace(microsecond=0)
this_date = this_date.strftime("%d.%m.%Y %H:%M:%S")
@@ -120,35 +127,50 @@ def get_date():
# Получение юникс даты
def get_unix():
return int(time.time())
def get_unix(full=False) -> int:
if full:
return time.time_ns()
else:
return int(time.time())
# Генерация пароля
def generate_password(len_password: int):
passwd = list("1234567890abcdefghigklmnopqrstuvyxwzABCDEFGHIGKLMNOPQRSTUVYXWZ")
random.shuffle(passwd)
random_chars = "".join([random.choice(passwd) for x in range(len_password)])
def gen_password(len_password: int = 16, type_password: str = "default") -> str: # default, number, letter, onechar
if type_password == "default":
char_password = list("1234567890abcdefghigklmnopqrstuvyxwzABCDEFGHIGKLMNOPQRSTUVYXWZ")
elif type_password == "letter":
char_password = list("abcdefghigklmnopqrstuvyxwzABCDEFGHIGKLMNOPQRSTUVYXWZ")
elif type_password == "number":
char_password = list("1234567890")
elif type_password == "onechar":
char_password = list("1234567890")
random.shuffle(char_password)
random_chars = "".join([random.choice(char_password) for x in range(len_password)])
if type_password == "onechar":
random_chars = f"{random.choice('abcdefghigklmnopqrstuvyxwzABCDEFGHIGKLMNOPQRSTUVYXWZ')}{random_chars[1:]}"
return random_chars
# Корректный вывод времени
def convert_times(get_time, get_type="day"):
def convert_times(get_time, get_type="day") -> str:
get_time = int(get_time)
if get_time < 0: get_time = 0
if get_type == "second":
get_list = ["секунда", "секунды", "секунд"]
get_list = ['секунда', 'секунды', 'секунд']
elif get_type == "minute":
get_list = ["минута", "минуты", "минут"]
get_list = ['минута', 'минуты', 'минут']
elif get_type == "hour":
get_list = ["час", "часа", "часов"]
get_list = ['час', 'часа', 'часов']
elif get_type == "day":
get_list = ["день", "дня", "дней"]
get_list = ['день', 'дня', 'дней']
elif get_type == "month":
get_list = ["месяц", "месяца", "месяцев"]
get_list = ['месяц', 'месяца', 'месяцев']
else:
get_list = ["год", "года", "лет"]
get_list = ['год', 'года', 'лет']
if get_time % 10 == 1 and get_time % 100 != 11:
count = 0
@@ -161,35 +183,57 @@ def convert_times(get_time, get_type="day"):
######################################## ЧИСЛА ########################################
# Преобразование длинных вещественных чисел в читаемый вид
def snum(amount, remains=0) -> str:
if "-" in str(amount):
str_amount = "%.*f" % (int(str(amount).split("-")[1]), amount)
elif "." in str(amount):
str_amount = f"{float(amount):.{len(str(amount).split('.')[1])}f}"
else:
str_amount = str(amount)
while str_amount.endswith('0'): str_amount = str_amount[:-1]
if str_amount.endswith('.'): str_amount = str_amount[:-1]
if remains != 0:
str_amount = round(float(str_amount), remains)
return str(str_amount)
# Конвертация числа в вещественное
def to_float(get_number, remains=2):
def to_float(get_number, remains=2) -> Union[int, float]:
if "," in str(get_number):
get_number = str(get_number).replace(",", ".")
if "." in get_number:
get_last = get_number.split(".")
if "." in str(get_number):
get_last = str(get_number).split(".")
if get_last[1].endswith("0"):
if str(get_last[1]).endswith("0"):
while True:
if get_number.endswith("0"):
get_number = get_number[:-1]
if str(get_number).endswith("0"):
get_number = str(get_number)[:-1]
else:
break
get_number = round(float(get_number), remains)
if str(float(get_number)).split(".")[1] == "0":
get_number = int(get_number)
str_number = snum(get_number)
if "." in str_number:
if str_number.split(".")[1] == "0":
get_number = int(get_number)
else:
get_number = float(get_number)
else:
get_number = float(get_number)
get_number = int(get_number)
return get_number
# Конвертация числа в целочисленное
def to_int(get_number):
def to_int(get_number) -> int:
if "," in get_number:
get_number = get_number.replace(",", ".")
get_number = str(get_number).replace(",", ".")
get_number = int(round(float(get_number)))
@@ -197,8 +241,8 @@ def to_int(get_number):
# Проверка числа на вещественное
def is_number(get_number):
if get_number.isdigit():
def is_number(get_number) -> bool:
if str(get_number).isdigit():
return False
else:
if "," in str(get_number): get_number = str(get_number).replace(",", ".")
@@ -210,18 +254,11 @@ def is_number(get_number):
return True
# Преобразование длинных вещественных чисел в читаемый вид
def show_floats(amount):
return f"{float(amount):.{len(str(amount).split('.')[1])}f}"
# Форматирование чисел в читаемый вид
def format_rate(rate, around=False):
# Форматирование числа в читаемый вид
def format_rate(rate, around=False) -> str:
rate = str(round(float(rate), 2))
if "," in rate:
rate = float(rate.replace(",", "."))
if "," in rate: rate = float(rate.replace(",", "."))
len_rate = str(int(float(rate)))
if len(len_rate) == 3:
@@ -241,7 +278,7 @@ def format_rate(rate, around=False):
elif len(len_rate) == 10:
get_rate = f"{len_rate[0:1]} {len_rate[1:4]} {len_rate[4:7]} {len_rate[7:]}"
else:
get_rate = 0
get_rate = "0"
if not around:
if "." in rate:
+2 -2
View File
@@ -13,12 +13,12 @@ async def startup_notify(bot: Bot):
# Автоматические бэкапы БД
async def autobackup(bot: Bot):
async def autobackup_admin(bot: Bot):
for admin in get_admins():
try:
await bot.send_document(admin,
FSInputFile(PATH_DATABASE),
caption=f"<b>📦 AUTOBACKUP</b>\n"
f"<code>🕰 {get_date()}</code>")
f"🕰 <code>{get_date()}</code>")
except:
pass