Кулдаун с помощью модуля datetime
Передо мной стоит задача - сделать таймер кулдаун использования команды для бота.
Если подробнее, то после того, как человек использует команду мне нужно сделать кулдаун в 24 часа, также нужно, чтобы при попытке использовать команду снова отправлялось время которое осталось человеку ждать.
Какие то представления о библиотеке я имею, исходя из прочтений нескольких статей на просторах интернета, но из за различного рода ошибок выполнить задачу не могу.
Буду рад если поможете=)
P.S. можете предложить вариант с библиотекой отличной от datetime
P.S.2 если как-то поможет делу - для бота я использую библиотеку aiogram
Ответы (3 шт):
Ну, раз вы не выкладываете свои наработки, ловите функцию которая работает на секундах обратного отсчета.
import time
def countdown(t):
while t:
m, s = divmod(t, 60)
timer = f'{m:02d}:{s:02d}'
print(timer, end="\r")
time.sleep(1)
t -= 1
print('Ну вот и все, таймер закончился!')
t = input("Сколько секунд будем считать: ")
countdown(int(t))
Переработайте под свои нужды, для суток используйте 86400
Так как вам нужно знать когда была нажата кнопка, то вам придется это где-то хранить. Варианты - FSM или База Данных. Покажу на примере FSM.
import time
from aiogram import Bot, Dispatcher, executor, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext
from data import config
bot = Bot(token=config.BOT_TOKEN)
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
@dp.message_handler(commands=['start'])
async def send_welcome(message: types.Message):
await message.answer("__", reply_markup=types.InlineKeyboardMarkup().add(
types.InlineKeyboardButton('Создать персонажа', callback_data='push_button')
))
@dp.callback_query_handler(text="push_button")
async def push_button(call: types.CallbackQuery, state: FSMContext):
await call.answer()
async with state.proxy() as data:
if type(data.get('button_pushed')) is float:
if time.time() - data['button_pushed'] < 86400:
hour = int((86400 - (time.time() - data['button_pushed'])) / 3600)
minute = int(((86400 - (time.time() - data['button_pushed'])) % 3600) / 60)
second = int(((86400 - (time.time() - data['button_pushed'])) % 3600) % 60)
await call.message.answer(f"Осталось ждать ещё {hour} часов {minute} минут {second} секунд")
return
data['button_pushed'] = time.time()
await call.message.answer("Кнопка нажата")
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)
Ну и на всякий напоминаю что при перезапуске бота, память (MemoryStorage) очищается. Если бот часто рестартится, то стоит юзать redis или mongoDB
В примере я использовал sqlite, но вы можете использовать другую БД. И в идеале создать отдельный класс для работы c БД.
Если вам нужно время в другом формате можете использовать datetime.
import time
import sqlite3
def get_time_now():
return int(str(time.time()).split(".")[0])
def save_time(user_id):
conn = sqlite3.connect('Название вашей бд')
cur = conn.cursor()
cur.execute(f"UPDATE Название таблицы SET lastUse='{get_time_now()}' WHERE userId='{user_id}'")
conn.commit()
return True
def check_time():
time_in_database = #Достаёте из бд время
if get_time_now() - time_in_database >= 60 * 60 * 24 or time_in_database == 0:
return True
return False
@dp.callback_query_handler(text="push_button")
async def push_button(call: types.CallbackQuery):
if check_time():
# Действия, которые будет происходить при нажатии
else:
await call.message.answer(f"Осталось ждать {time.strftime('%H:%M:%S', time.gmtime('Достаёте сюда время из бд' - get_time_now()))}")
save_time(call.from_user.id)
