refactor for new aiogram
This commit is contained in:
parent
4c334e0e32
commit
49942b83ed
|
@ -1,16 +1,16 @@
|
||||||
FROM python:3.8 AS builder
|
FROM python:3.12 AS builder
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
|
|
||||||
# install dependencies to the local user directory (eg. /root/.local)
|
# install dependencies to the local user directory (eg. /root/.local)
|
||||||
RUN pip install --user -r requirements.txt
|
RUN pip3 install --user -r requirements.txt
|
||||||
|
|
||||||
# second stage
|
# second stage
|
||||||
FROM python:3.8-slim
|
FROM python:3.12-slim
|
||||||
WORKDIR /code
|
WORKDIR /code
|
||||||
|
|
||||||
# copy only the dependencies that are needed for our application and the source files
|
# copy only the dependencies that are needed for our application and the source files
|
||||||
COPY --from=builder /root/.local /root/.local
|
COPY --from=builder /root/.local /root/.local
|
||||||
COPY ./src .
|
COPY ./source .
|
||||||
|
|
||||||
# update PATH
|
# update PATH
|
||||||
ENV PATH=/root/.local:$PATH
|
ENV PATH=/root/.local:$PATH
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
# expense-bot
|
||||||
|
|
||||||
|
## Local run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
# [WIP]
|
# [WIP]
|
||||||
|
|
||||||
# Build Image
|
# Build Image
|
||||||
|
@ -14,4 +24,4 @@ $ podman push [hash]|[localhost/expense-bot:0.1.0] docker://quay.io/ksemele/expe
|
||||||
$ podman login quay.io
|
$ podman login quay.io
|
||||||
$ podman pull quay.io/ksemele/expense-bot
|
$ podman pull quay.io/ksemele/expense-bot
|
||||||
$ podman pull quay.io/ksemele/expense-bot:0.1.0
|
$ podman pull quay.io/ksemele/expense-bot:0.1.0
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
aiogram<3.0
|
aiogram~=3.3.0
|
||||||
environs==9.5.0
|
environs==9.5.0
|
||||||
requests~=2.27.1
|
requests~=2.27.1
|
|
@ -0,0 +1,55 @@
|
||||||
|
from loader import *
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message(CommandStart())
|
||||||
|
async def command_start_handler(message: Message) -> None:
|
||||||
|
"""
|
||||||
|
This handler receives messages with `/start` command
|
||||||
|
"""
|
||||||
|
# Most event objects have aliases for API methods that can be called in events' context
|
||||||
|
# For example if you want to answer to incoming message you can use `message.answer(...)` alias
|
||||||
|
# and the target chat will be passed to :ref:`aiogram.methods.send_message.SendMessage`
|
||||||
|
# method automatically or call API method directly via
|
||||||
|
# Bot instance: `bot.send_message(chat_id=message.chat.id, ...)`
|
||||||
|
await message.answer(f"Hello, {hbold(message.from_user.full_name)}!")
|
||||||
|
|
||||||
|
|
||||||
|
# @dp.message()
|
||||||
|
# async def echo_handler(message: types.Message) -> None:
|
||||||
|
# """
|
||||||
|
# Handler will forward receive a message back to the sender
|
||||||
|
|
||||||
|
# By default, message handler will handle all message types (like a text, photo, sticker etc.)
|
||||||
|
# """
|
||||||
|
# try:
|
||||||
|
# # Send a copy of the received message
|
||||||
|
# await message.send_copy(chat_id=message.chat.id)
|
||||||
|
# except TypeError:
|
||||||
|
# # But not all the types is supported to be copied so need to handle it
|
||||||
|
# await message.answer("Nice try!")
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message(Command("currencies"))
|
||||||
|
async def get_currencies(message: types.Message):
|
||||||
|
url = "https://nbg.gov.ge/gw/api/ct/monetarypolicy/currencies/en/json/"
|
||||||
|
date = datetime.date.today().isoformat()
|
||||||
|
payload = {"currencies": ["USD", "EUR"], "date": date}
|
||||||
|
r = requests.get(url, params=payload)
|
||||||
|
# print(r.text)
|
||||||
|
usd = json.loads(r.text)
|
||||||
|
for elem in usd:
|
||||||
|
# print(elem['currencies'])
|
||||||
|
for each in elem["currencies"]:
|
||||||
|
# print(each)
|
||||||
|
# print(each['code'] + " " + each['rateFormated'])
|
||||||
|
await message.answer(each["code"] + " " + each["rateFormated"])
|
||||||
|
# print(r.status_code)
|
||||||
|
|
||||||
|
|
||||||
|
async def main() -> None:
|
||||||
|
await dp.start_polling(bot)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
|
||||||
|
asyncio.run(main())
|
|
@ -0,0 +1,8 @@
|
||||||
|
from environs import Env
|
||||||
|
|
||||||
|
env = Env()
|
||||||
|
env.read_env()
|
||||||
|
|
||||||
|
BOT_TOKEN = env.str("BOT_TOKEN")
|
||||||
|
ADMINS = env.list("ADMINS")
|
||||||
|
IP = env.str("HOST_IP")
|
|
@ -0,0 +1,26 @@
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
import datetime
|
||||||
|
from os import getenv
|
||||||
|
|
||||||
|
from aiogram import Bot, Dispatcher, Router, types
|
||||||
|
from aiogram.enums import ParseMode
|
||||||
|
from aiogram.filters import CommandStart
|
||||||
|
from aiogram.types import Message
|
||||||
|
from aiogram.utils.markdown import hbold
|
||||||
|
from aiogram.filters import (
|
||||||
|
Command,
|
||||||
|
CommandObject,
|
||||||
|
ExceptionMessageFilter,
|
||||||
|
ExceptionTypeFilter,
|
||||||
|
)
|
||||||
|
# envs from .env file
|
||||||
|
from data import config
|
||||||
|
|
||||||
|
# Initialize Bot instance with a default parse mode which will be passed to all API calls
|
||||||
|
# And the run events dispatching
|
||||||
|
bot = Bot(token=config.BOT_TOKEN, parse_mode=ParseMode.HTML)
|
||||||
|
dp = Dispatcher()
|
19
src/app.py
19
src/app.py
|
@ -1,19 +0,0 @@
|
||||||
from aiogram import executor
|
|
||||||
|
|
||||||
from loader import dp
|
|
||||||
import middlewares, filters, handlers
|
|
||||||
from utils.notify_admins import on_startup_notify
|
|
||||||
from utils.set_bot_commands import set_default_commands
|
|
||||||
|
|
||||||
|
|
||||||
async def on_startup(dispatcher):
|
|
||||||
# Устанавливаем дефолтные команды
|
|
||||||
await set_default_commands(dispatcher)
|
|
||||||
|
|
||||||
# Уведомляет про запуск
|
|
||||||
await on_startup_notify(dispatcher)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
executor.start_polling(dp, on_startup=on_startup)
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
from environs import Env
|
|
||||||
|
|
||||||
# Теперь используем вместо библиотеки python-dotenv библиотеку environs
|
|
||||||
env = Env()
|
|
||||||
env.read_env()
|
|
||||||
|
|
||||||
BOT_TOKEN = env.str("BOT_TOKEN") # Забираем значение типа str
|
|
||||||
ADMINS = env.list("ADMINS") # Тут у нас будет список из админов
|
|
||||||
IP = env.str("ip") # Тоже str, но для айпи адреса хоста
|
|
|
@ -1,9 +0,0 @@
|
||||||
from aiogram import Dispatcher
|
|
||||||
|
|
||||||
from loader import dp
|
|
||||||
# from .is_admin import AdminFilter
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "filters":
|
|
||||||
# dp.filters_factory.bind(AdminFilter)
|
|
||||||
pass
|
|
|
@ -1,5 +0,0 @@
|
||||||
from . import errors
|
|
||||||
from . import users
|
|
||||||
from . import groups
|
|
||||||
from . import channels
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
from . import error_handler
|
|
|
@ -1,36 +0,0 @@
|
||||||
import logging
|
|
||||||
from aiogram.utils.exceptions import (TelegramAPIError,
|
|
||||||
MessageNotModified,
|
|
||||||
CantParseEntities)
|
|
||||||
|
|
||||||
|
|
||||||
from loader import dp
|
|
||||||
|
|
||||||
|
|
||||||
@dp.errors_handler()
|
|
||||||
async def errors_handler(update, exception):
|
|
||||||
"""
|
|
||||||
Exceptions handler. Catches all exceptions within task factory tasks.
|
|
||||||
:param dispatcher:
|
|
||||||
:param update:
|
|
||||||
:param exception:
|
|
||||||
:return: stdout logging
|
|
||||||
"""
|
|
||||||
|
|
||||||
if isinstance(exception, MessageNotModified):
|
|
||||||
logging.exception('Message is not modified')
|
|
||||||
# do something here?
|
|
||||||
return True
|
|
||||||
|
|
||||||
if isinstance(exception, CantParseEntities):
|
|
||||||
# or here
|
|
||||||
logging.exception(f'CantParseEntities: {exception} \nUpdate: {update}')
|
|
||||||
return True
|
|
||||||
|
|
||||||
# MUST BE THE LAST CONDITION (ЭТО УСЛОВИЕ ВСЕГДА ДОЛЖНО БЫТЬ В КОНЦЕ)
|
|
||||||
if isinstance(exception, TelegramAPIError):
|
|
||||||
logging.exception(f'TelegramAPIError: {exception} \nUpdate: {update}')
|
|
||||||
return True
|
|
||||||
|
|
||||||
# At least you have tried.
|
|
||||||
logging.exception(f'Update: {update} \n{exception}')
|
|
|
@ -1,7 +0,0 @@
|
||||||
from . import help
|
|
||||||
from . import start
|
|
||||||
from . import echo
|
|
||||||
from . import add
|
|
||||||
from . import settings
|
|
||||||
from . import test
|
|
||||||
from . import currencies
|
|
|
@ -1,25 +0,0 @@
|
||||||
from aiogram import types
|
|
||||||
from loader import dp
|
|
||||||
import sqlite3 as sl
|
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(commands="add")
|
|
||||||
async def bot_add(message: types.Message):
|
|
||||||
await message.answer(f"This is ADD command, {message.from_user.username}!")
|
|
||||||
con = sl.connect('test.db')
|
|
||||||
|
|
||||||
# @dp.message_handler(state=None) # todo сделать стейты. сейчас это хэндлит все сообщения в любых состояниях!
|
|
||||||
# async def bot_add_parse_message(message: types.Message):
|
|
||||||
# words = message.text.split()
|
|
||||||
# # Uncomment to see debug in console
|
|
||||||
# # print('Split message:')
|
|
||||||
# # i = 0
|
|
||||||
# # for each in words:
|
|
||||||
# # print('[' + str(i) + ']: ' + '[' + each + ']')
|
|
||||||
# # i += 1
|
|
||||||
# # print('[end]')
|
|
||||||
#
|
|
||||||
# if len(words) == 2:
|
|
||||||
# await message.answer('[added] ' + words[0] + ' ' + words[1])
|
|
||||||
# else:
|
|
||||||
# await message.answer("can't parse. wrong arguments!")
|
|
|
@ -1,22 +0,0 @@
|
||||||
from aiogram import types
|
|
||||||
from loader import dp
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(commands="currencies")
|
|
||||||
async def get_currencies(message: types.Message):
|
|
||||||
import requests
|
|
||||||
import datetime
|
|
||||||
url = 'https://nbg.gov.ge/gw/api/ct/monetarypolicy/currencies/en/json/'
|
|
||||||
date = datetime.date.today().isoformat()
|
|
||||||
payload = {'currencies': ['USD', 'EUR'], 'date': date}
|
|
||||||
r = requests.get(url, params=payload)
|
|
||||||
print(r.text)
|
|
||||||
usd = json.loads(r.text)
|
|
||||||
for elem in usd:
|
|
||||||
# print(elem['currencies'])
|
|
||||||
for each in elem['currencies']:
|
|
||||||
# print(each)
|
|
||||||
# print(each['code'] + " " + each['rateFormated'])
|
|
||||||
await message.answer(each['code'] + " " + each['rateFormated'])
|
|
||||||
# print(r.status_code)
|
|
|
@ -1,21 +0,0 @@
|
||||||
from aiogram import types
|
|
||||||
from aiogram.dispatcher import FSMContext
|
|
||||||
|
|
||||||
# from loader import dp
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# # Эхо хендлер, куда летят текстовые сообщения без указанного состояния
|
|
||||||
# @dp.message_handler(state=None)
|
|
||||||
# async def bot_echo(message: types.Message):
|
|
||||||
# await message.answer(f"Эхо без состояния."
|
|
||||||
# f"Сообщение:\n"
|
|
||||||
# f"{message.text}")
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# # Эхо хендлер, куда летят ВСЕ сообщения с указанным состоянием
|
|
||||||
# @dp.message_handler(state="*", content_types=types.ContentTypes.ANY)
|
|
||||||
# async def bot_echo_all(message: types.Message, state: FSMContext):
|
|
||||||
# state = await state.get_state()
|
|
||||||
# await message.answer(f"Эхо в состоянии <code>{state}</code>.\n"
|
|
||||||
# f"\nСодержание сообщения:\n"
|
|
||||||
# f"<code>{message}</code>")
|
|
|
@ -1,20 +0,0 @@
|
||||||
from aiogram import types
|
|
||||||
from aiogram.dispatcher.filters.builtin import CommandHelp
|
|
||||||
|
|
||||||
from loader import dp
|
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(CommandHelp())
|
|
||||||
async def bot_help(message: types.Message):
|
|
||||||
text = ("Available commands: ",
|
|
||||||
"/start - Launch bot.",
|
|
||||||
"/help - Commands list, little help.",
|
|
||||||
"/add - Add expense.",
|
|
||||||
"/edit - Edit expense.",
|
|
||||||
"/list - See my expenses.",
|
|
||||||
"/settings - Configure bot.",
|
|
||||||
"/currencies - Get Official Georgian course",
|
|
||||||
"/test - Test command."
|
|
||||||
)
|
|
||||||
|
|
||||||
await message.answer("\n".join(text))
|
|
|
@ -1,9 +0,0 @@
|
||||||
from aiogram import types
|
|
||||||
from aiogram.dispatcher.filters.builtin import CommandSettings
|
|
||||||
|
|
||||||
from loader import dp
|
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(CommandSettings())
|
|
||||||
async def bot_settings(message: types.Message):
|
|
||||||
await message.answer(f"Settings being here...")
|
|
|
@ -1,9 +0,0 @@
|
||||||
from aiogram import types
|
|
||||||
from aiogram.dispatcher.filters.builtin import CommandStart
|
|
||||||
|
|
||||||
from loader import dp
|
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(CommandStart())
|
|
||||||
async def bot_start(message: types.Message):
|
|
||||||
await message.answer(f"Hello, {message.from_user.username}!")
|
|
|
@ -1,76 +0,0 @@
|
||||||
from aiogram import types
|
|
||||||
from loader import dp
|
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(commands="test")
|
|
||||||
async def cmd_random(message: types.Message):
|
|
||||||
keyboard = types.InlineKeyboardMarkup()
|
|
||||||
keyboard.add(types.InlineKeyboardButton(text="Нажми меня", callback_data="random_value"))
|
|
||||||
keyboard.add(types.InlineKeyboardButton(text="Нажми меня 2", callback_data="random_value2"))
|
|
||||||
await message.answer("test reply 1-2-3", reply_markup=keyboard)
|
|
||||||
|
|
||||||
|
|
||||||
@dp.callback_query_handler(text="random_value")
|
|
||||||
async def send_random_value(call: types.CallbackQuery):
|
|
||||||
await call.message.answer('test reply 1')
|
|
||||||
# shows alert with 'Ok' button
|
|
||||||
await call.answer(text="Спасибо, что воспользовались ботом!", show_alert=True)
|
|
||||||
# или просто await call.answer()
|
|
||||||
|
|
||||||
|
|
||||||
@dp.callback_query_handler(text="random_value2")
|
|
||||||
async def send_random_value(call: types.CallbackQuery):
|
|
||||||
await call.message.answer('test reply 2')
|
|
||||||
await call.answer()
|
|
||||||
|
|
||||||
########################################################################################
|
|
||||||
from aiogram.utils.callback_data import CallbackData
|
|
||||||
from aiogram.utils.exceptions import MessageNotModified
|
|
||||||
from contextlib import suppress
|
|
||||||
# fabnum - префикс, action - название аргумента, которым будем передавать значение
|
|
||||||
callback_numbers = CallbackData("fabnum", "action")
|
|
||||||
# Здесь хранятся пользовательские данные.
|
|
||||||
# Т.к. это словарь в памяти, то при перезапуске он очистится
|
|
||||||
user_data = {}
|
|
||||||
|
|
||||||
|
|
||||||
def get_keyboard_fab():
|
|
||||||
buttons = [
|
|
||||||
types.InlineKeyboardButton(text="-1", callback_data=callback_numbers.new(action="decr")),
|
|
||||||
types.InlineKeyboardButton(text="+1", callback_data=callback_numbers.new(action="incr")),
|
|
||||||
types.InlineKeyboardButton(text="Подтвердить", callback_data=callback_numbers.new(action="finish"))
|
|
||||||
]
|
|
||||||
keyboard = types.InlineKeyboardMarkup(row_width=2)
|
|
||||||
keyboard.add(*buttons)
|
|
||||||
return keyboard
|
|
||||||
|
|
||||||
|
|
||||||
async def update_num_text_fab(message: types.Message, new_value: int):
|
|
||||||
with suppress(MessageNotModified):
|
|
||||||
await message.edit_text(f"Укажите число: {new_value}", reply_markup=get_keyboard_fab())
|
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(commands="numbers_fab")
|
|
||||||
async def cmd_numbers(message: types.Message):
|
|
||||||
user_data[message.from_user.id] = 0
|
|
||||||
await message.answer("Укажите число: 0", reply_markup=get_keyboard_fab())
|
|
||||||
|
|
||||||
|
|
||||||
@dp.callback_query_handler(callback_numbers.filter(action=["incr", "decr"]))
|
|
||||||
async def callbacks_num_change_fab(call: types.CallbackQuery, callback_data: dict):
|
|
||||||
user_value = user_data.get(call.from_user.id, 0)
|
|
||||||
action = callback_data["action"]
|
|
||||||
if action == "incr":
|
|
||||||
user_data[call.from_user.id] = user_value + 1
|
|
||||||
await update_num_text_fab(call.message, user_value + 1)
|
|
||||||
elif action == "decr":
|
|
||||||
user_data[call.from_user.id] = user_value - 1
|
|
||||||
await update_num_text_fab(call.message, user_value - 1)
|
|
||||||
await call.answer()
|
|
||||||
|
|
||||||
|
|
||||||
@dp.callback_query_handler(callback_numbers.filter(action=["finish"]))
|
|
||||||
async def callbacks_num_finish_fab(call: types.CallbackQuery):
|
|
||||||
user_value = user_data.get(call.from_user.id, 0)
|
|
||||||
await call.message.edit_text(f"Итого: {user_value}")
|
|
||||||
await call.answer()
|
|
|
@ -1,2 +0,0 @@
|
||||||
from . import default
|
|
||||||
from . import inline
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
from aiogram import Bot, Dispatcher, types
|
|
||||||
from aiogram.contrib.fsm_storage.memory import MemoryStorage
|
|
||||||
|
|
||||||
from data import config
|
|
||||||
|
|
||||||
bot = Bot(token=config.BOT_TOKEN, parse_mode=types.ParseMode.HTML)
|
|
||||||
storage = MemoryStorage()
|
|
||||||
dp = Dispatcher(bot, storage=storage)
|
|
|
@ -1,8 +0,0 @@
|
||||||
from aiogram import Dispatcher
|
|
||||||
|
|
||||||
from loader import dp
|
|
||||||
from .throttling import ThrottlingMiddleware
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "middlewares":
|
|
||||||
dp.middleware.setup(ThrottlingMiddleware())
|
|
|
@ -1,37 +0,0 @@
|
||||||
import asyncio
|
|
||||||
|
|
||||||
from aiogram import types, Dispatcher
|
|
||||||
from aiogram.dispatcher import DEFAULT_RATE_LIMIT
|
|
||||||
from aiogram.dispatcher.handler import CancelHandler, current_handler
|
|
||||||
from aiogram.dispatcher.middlewares import BaseMiddleware
|
|
||||||
from aiogram.utils.exceptions import Throttled
|
|
||||||
|
|
||||||
|
|
||||||
class ThrottlingMiddleware(BaseMiddleware):
|
|
||||||
"""
|
|
||||||
Simple middleware
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, limit=DEFAULT_RATE_LIMIT, key_prefix='antiflood_'):
|
|
||||||
self.rate_limit = limit
|
|
||||||
self.prefix = key_prefix
|
|
||||||
super(ThrottlingMiddleware, self).__init__()
|
|
||||||
|
|
||||||
async def on_process_message(self, message: types.Message, data: dict):
|
|
||||||
handler = current_handler.get()
|
|
||||||
dispatcher = Dispatcher.get_current()
|
|
||||||
if handler:
|
|
||||||
limit = getattr(handler, "throttling_rate_limit", self.rate_limit)
|
|
||||||
key = getattr(handler, "throttling_key", f"{self.prefix}_{handler.__name__}")
|
|
||||||
else:
|
|
||||||
limit = self.rate_limit
|
|
||||||
key = f"{self.prefix}_message"
|
|
||||||
try:
|
|
||||||
await dispatcher.throttle(key, rate=limit)
|
|
||||||
except Throttled as t:
|
|
||||||
await self.message_throttled(message, t)
|
|
||||||
raise CancelHandler()
|
|
||||||
|
|
||||||
async def message_throttled(self, message: types.Message, throttled: Throttled):
|
|
||||||
if throttled.exceeded_count <= 2:
|
|
||||||
await message.reply("Too many requests!")
|
|
|
@ -1,3 +0,0 @@
|
||||||
from . import db_api
|
|
||||||
from . import misc
|
|
||||||
from .notify_admins import on_startup_notify
|
|
|
@ -1,2 +0,0 @@
|
||||||
from .throttling import rate_limit
|
|
||||||
from . import logging
|
|
|
@ -1,6 +0,0 @@
|
||||||
import logging
|
|
||||||
|
|
||||||
logging.basicConfig(format=u'%(filename)s [LINE:%(lineno)d] #%(levelname)-8s [%(asctime)s] %(message)s',
|
|
||||||
level=logging.INFO,
|
|
||||||
# level=logging.DEBUG, # Можно заменить на другой уровень логгирования.
|
|
||||||
)
|
|
|
@ -1,16 +0,0 @@
|
||||||
def rate_limit(limit: int, key=None):
|
|
||||||
"""
|
|
||||||
Decorator for configuring rate limit and key in different functions.
|
|
||||||
|
|
||||||
:param limit:
|
|
||||||
:param key:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
|
|
||||||
def decorator(func):
|
|
||||||
setattr(func, 'throttling_rate_limit', limit)
|
|
||||||
if key:
|
|
||||||
setattr(func, 'throttling_key', key)
|
|
||||||
return func
|
|
||||||
|
|
||||||
return decorator
|
|
|
@ -1,14 +0,0 @@
|
||||||
import logging
|
|
||||||
|
|
||||||
from aiogram import Dispatcher
|
|
||||||
|
|
||||||
from data.config import ADMINS
|
|
||||||
|
|
||||||
|
|
||||||
async def on_startup_notify(dp: Dispatcher):
|
|
||||||
for admin in ADMINS:
|
|
||||||
try:
|
|
||||||
await dp.bot.send_message(admin, "Voodoo21-expense started")
|
|
||||||
|
|
||||||
except Exception as err:
|
|
||||||
logging.exception(err)
|
|
|
@ -1,17 +0,0 @@
|
||||||
from aiogram import types
|
|
||||||
|
|
||||||
|
|
||||||
async def set_default_commands(dp):
|
|
||||||
await dp.bot.set_my_commands(
|
|
||||||
[
|
|
||||||
types.BotCommand("start", "Launch bot."),
|
|
||||||
types.BotCommand("help", "Commands list, little help."),
|
|
||||||
types.BotCommand("add", "Add expense."),
|
|
||||||
types.BotCommand("edit", "Edit expense."),
|
|
||||||
types.BotCommand("list", "See my expenses."),
|
|
||||||
types.BotCommand("settings", "Configure bot."),
|
|
||||||
types.BotCommand("currencies", "USD\EUR - GEL."),
|
|
||||||
types.BotCommand("test", "Test command."),
|
|
||||||
# types.BotCommand("settings3", "Configure bot."),
|
|
||||||
]
|
|
||||||
)
|
|
Loading…
Reference in New Issue