mirror of
https://github.com/EDeev/y.calendarkin.git
synced 2026-10-08 00:39:27 +03:00
Версия на aiogram 3 — та, что работает на сервере
В репозитории оставался код на aiogram 2 (executor, message_handler), а requirements.txt уже требовал aiogram 3 — по README бот не запускался (issue #1). Переписанная версия с разделением на bot.py / handlers.py / init.py давно работала на сервере, теперь она и здесь. Переводы строк приведены к LF.
This commit is contained in:
parent
31bf093d94
commit
18e79e24a5
6 changed files with 354 additions and 356 deletions
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
* text=auto eol=lf
|
||||
*.jpg binary
|
||||
*.db binary
|
||||
269
code/bot.py
269
code/bot.py
|
|
@ -1,235 +1,8 @@
|
|||
import logging, config, sql, asyncio, wget, os
|
||||
import asyncio, logging, time, wget, os
|
||||
|
||||
from aiogram import Bot, Dispatcher, executor, types
|
||||
from aiogram.types import ParseMode
|
||||
|
||||
from datetime import datetime, time
|
||||
from script import text_ical, message_form, dt_now, delta_time
|
||||
|
||||
# инициализируем токен
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
bot = Bot(token=config.TOKEN)
|
||||
dp = Dispatcher(bot)
|
||||
|
||||
# инициализируем соединение с БД
|
||||
du = sql.Users('../db/users.db')
|
||||
dc = sql.Clock('../db/clock.db')
|
||||
|
||||
|
||||
# ПРИВЕТСТВЕННОЕ СООБЩЕНИЕ
|
||||
@dp.message_handler(commands=['start', 'help'])
|
||||
async def helps(message: types.Message):
|
||||
tg_id = int(message.chat.id)
|
||||
if not du.user_exists(tg_id):
|
||||
du.add_user(tg_id)
|
||||
|
||||
buttons = [types.InlineKeyboardButton(text="КОМАНДЫ", callback_data="com"),
|
||||
types.InlineKeyboardButton(text="АВТОР", callback_data="auth")]
|
||||
|
||||
keyboard = types.InlineKeyboardMarkup(row_width=2)
|
||||
keyboard.add(*buttons)
|
||||
|
||||
await message.answer(text="<b>Я.Календаркин</b> - бот для оповещения о событиях из <b>Яндекс.Календаря</b>. "
|
||||
"Для начала работы вам нужно всего лишь прислать в чат ссылку экспорта календаря в "
|
||||
"<b>формате ICal</b>. После получения ссылки, бот начнёт оповещать о всех новых событиях "
|
||||
"и появится возможность настройки оповещений. О том, какие команды есть для настройки, "
|
||||
"вы можете ознакомиться по кнопке <b>КОМАНДЫ</b>",
|
||||
parse_mode=ParseMode.HTML, reply_markup=keyboard)
|
||||
|
||||
|
||||
@dp.callback_query_handler(text="auth")
|
||||
async def author(call: types.CallbackQuery):
|
||||
await call.message.answer(text='*| АВТОР |*\n\n*>>* Этот бот не коммерческий проект, для упрощенного получения '
|
||||
'уведомлений о событиях в Яндекс.Календаре. Не многим этот бот будет полезен, но '
|
||||
'людям, чья работа подразумевает его использование, он станет лишь удобным '
|
||||
'инструментом. Я же пишу подобные небольшие проекты, о которых вы можете узнать '
|
||||
'больше на моём [GitHub](https://github.com/IGlek).',
|
||||
parse_mode=ParseMode.MARKDOWN)
|
||||
|
||||
|
||||
@dp.callback_query_handler(text="com")
|
||||
async def commands(call: types.CallbackQuery):
|
||||
await call.message.answer(text='<b>| КОМАНДЫ |</b>\n\n'
|
||||
'<b>/help</b> - вспомогательная функция для уточнения работы команд\n'
|
||||
'<b>/list</b> - список событий календаря, запланированных на сегодняшний день\n'
|
||||
'<b>/notif</b> - команда, отключающая рассылку уведомлений, даже при наличии событий в календаре\n'
|
||||
'<b>/daily</b> - оповещение в 8 утра по вашему часовому поясу со списком событий на день\n'
|
||||
'<b>/moment</b> - напоминание, приходящее в момент начала события\n\n'
|
||||
'<b>/get_alarm</b> - информация о времени на которое настроены оповещения\n'
|
||||
'<b>/edit_alarm</b> - изменение времени оповещений\n'
|
||||
'<b>/stop_alarm</b> - команда, отключающая второе оповещение о событии',
|
||||
parse_mode=types.ParseMode.HTML)
|
||||
|
||||
|
||||
# КОМАНДЫ
|
||||
@dp.message_handler(commands=['list'])
|
||||
async def check_list(message: types.Message):
|
||||
user_id = du.get_user_id(int(message.chat.id))
|
||||
|
||||
if du.url_exists(user_id):
|
||||
txt = "<b>Имеющиеся события на сегодня</b>\n\n"
|
||||
|
||||
lst_events = sorted(text_ical(user_id, du.get_tz(user_id)))
|
||||
today = dt_now(du.get_tz(user_id)).date()
|
||||
|
||||
counter = 0
|
||||
for event in lst_events:
|
||||
if event[0] == today:
|
||||
counter += 1
|
||||
txt += message_form(counter, event[3])
|
||||
|
||||
if counter:
|
||||
await message.answer(text=txt, parse_mode=ParseMode.HTML)
|
||||
else:
|
||||
await message.answer(text="<b>В данный момент</b> событий на сегодня найдено не было!",
|
||||
parse_mode=ParseMode.HTML)
|
||||
else:
|
||||
await message.answer("Для отображения событий вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
@dp.message_handler(commands=['notif'])
|
||||
async def notif_up(message: types.Message):
|
||||
user_id = du.get_user_id(int(message.chat.id))
|
||||
|
||||
if du.url_exists(user_id):
|
||||
if du.get_status(user_id):
|
||||
await message.answer("Уведомления о событиях выключены!")
|
||||
else:
|
||||
await message.answer("Уведомления о событиях включены!")
|
||||
|
||||
du.update_status(user_id)
|
||||
else:
|
||||
await message.answer("Для взаимодействия с событиями вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
@dp.message_handler(commands=['daily'])
|
||||
async def daily_up(message: types.Message):
|
||||
user_id = du.get_user_id(int(message.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
if dc.get_daily(user_id):
|
||||
await message.answer("Ежедневные утренние уведомления выключены!")
|
||||
else:
|
||||
await message.answer("Ежедневные утренние уведомления включены!")
|
||||
|
||||
dc.update_daily(user_id)
|
||||
else:
|
||||
await message.answer("Для взаимодействия с событиями вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
@dp.message_handler(commands=['moment'])
|
||||
async def start_up(message: types.Message):
|
||||
user_id = du.get_user_id(int(message.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
if dc.get_start(user_id):
|
||||
await message.answer("Уведомления в момент события выключены!")
|
||||
else:
|
||||
await message.answer("Уведомления в момент события включены!")
|
||||
|
||||
dc.update_start(user_id)
|
||||
else:
|
||||
await message.answer("Для взаимодействия с событиями вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
@dp.message_handler(commands=['get_alarm'])
|
||||
async def start_up(message: types.Message):
|
||||
user_id = du.get_user_id(int(message.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
alarms = dc.get_alarm(user_id)
|
||||
start = dc.get_start(user_id)
|
||||
status2 = dc.get_status2(user_id)
|
||||
|
||||
txt = ""
|
||||
|
||||
if status2:
|
||||
txt += "<b>У вас работает два оповещения"
|
||||
else:
|
||||
txt += "<b>У вас работает лишь первое оповещение"
|
||||
|
||||
if start:
|
||||
txt += " и сообщение в момент начала события!</b>"
|
||||
else:
|
||||
txt += "!</b>"
|
||||
|
||||
await message.answer(text=(txt + f"\n\n<b>Первое оповещение</b> приходит за {alarms[0]} минут\n"
|
||||
f"<b>Второе оповещение</b> приходит за {alarms[1]} минут"),
|
||||
parse_mode=ParseMode.HTML)
|
||||
else:
|
||||
await message.answer("Для того, чтобы получить таймеры, вы должны прислать ical-ссылку на свой календарь!")
|
||||
|
||||
|
||||
@dp.message_handler(commands=['edit_alarm'])
|
||||
async def start_up(message: types.Message):
|
||||
user_id = du.get_user_id(int(message.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
await message.bot.send_photo(chat_id=message.chat.id, photo=open("../data/photo_edit_alarm.jpg", "rb"),
|
||||
caption="Для изменения времени вам надо в ответ на это сообщение прислать два "
|
||||
"числа через пробел: разница времени первого и второго таймера по ходу "
|
||||
"времени соответственно")
|
||||
else:
|
||||
await message.answer("Для того, чтобы изменить таймеры, вы должны прислать ical-ссылку на свой календарь!")
|
||||
|
||||
|
||||
@dp.message_handler(commands=['stop_alarm'])
|
||||
async def daily_up(message: types.Message):
|
||||
user_id = du.get_user_id(int(message.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
if dc.get_status2(user_id):
|
||||
await message.answer("Второе уведомление выключено!")
|
||||
else:
|
||||
await message.answer("Второе уведомление включено!")
|
||||
|
||||
dc.update_status2(user_id)
|
||||
else:
|
||||
await message.answer("Для взаимодействия с событиями вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
# ЗАГРУЗКА ССЫЛКИ
|
||||
@dp.message_handler(content_types=['text'])
|
||||
async def downloading_file_ics(message: types.Message):
|
||||
user_id = du.get_user_id(int(message.chat.id))
|
||||
|
||||
if message.text[:5] == "https":
|
||||
try:
|
||||
wget.download(message.text, f'../data/icals/{str(user_id)}_new.ics')
|
||||
|
||||
try:
|
||||
os.remove(f'../data/icals/{str(user_id)}.ics')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
os.rename(f'../data/icals/{str(user_id)}_new.ics', f'../data/icals/{str(user_id)}.ics')
|
||||
|
||||
time_zone = message.text.split("=")[-1]
|
||||
if not du.url_exists(user_id):
|
||||
du.add_url(user_id, message.text, time_zone)
|
||||
dc.add_clock(user_id)
|
||||
else:
|
||||
du.update_url(user_id, message.text, time_zone)
|
||||
|
||||
await message.answer("Ссылка успешно добавлена! Уведомления уже включены!")
|
||||
except Exception:
|
||||
await message.answer("Ошибка скачивания! Проверьте правильность ссылки и пришлите ещё раз")
|
||||
|
||||
if 'reply_to_message' in message and dc.clock_exists(user_id):
|
||||
text = "Для изменения времени вам надо в ответ на это сообщение прислать два числа через " \
|
||||
"пробел: разница времени первого и второго таймера по ходу времени соответственно"
|
||||
|
||||
if message.reply_to_message.caption == text:
|
||||
alarm_new = message.text.split()
|
||||
|
||||
if int(alarm_new[0]) < 60 and int(alarm_new[1]) < 60:
|
||||
dc.update_alarm1(user_id, int(alarm_new[0]))
|
||||
dc.update_alarm2(user_id, int(alarm_new[1]))
|
||||
|
||||
await message.answer("Время отправки уведомлений успешно обновлено!")
|
||||
else:
|
||||
await message.answer("Время отправки уведомлений должно быть меньше 60 минут!")
|
||||
from init import *
|
||||
from script import *
|
||||
from handlers import router
|
||||
|
||||
|
||||
# ПРОВЕРКА НА СОБЫТИЕ
|
||||
|
|
@ -273,29 +46,27 @@ async def alarm(wait_for):
|
|||
|
||||
delta_start = delta_time(d_event, 1, 0)
|
||||
if start and delta_start[0] < time_check <= delta_start[1]:
|
||||
await bot.send_message(chat_id=tg_id, parse_mode=ParseMode.HTML,
|
||||
await bot.send_message(chat_id=tg_id, disable_web_page_preview=True,
|
||||
text=f"<b>Событие начинается!</b>\n\n" + message_form(0, event[3]))
|
||||
|
||||
delta_alarm1 = delta_time(d_event, alarm[0], alarm[0] - 1)
|
||||
if delta_alarm1[0] < time_check <= delta_alarm1[1]:
|
||||
await bot.send_message(chat_id=tg_id, parse_mode=ParseMode.HTML,
|
||||
await bot.send_message(chat_id=tg_id, disable_web_page_preview=True,
|
||||
text=f"<b>Напоминаю!</b>\n<i>Через {alarm[0]} минут "
|
||||
f"будет событие:</i>\n\n{message_form(0, event[3])}")
|
||||
|
||||
if alarm2_status:
|
||||
delta_alarm2 = delta_time(d_event, alarm[1], alarm[1] - 1)
|
||||
if delta_alarm2[0] < time_check <= delta_alarm2[1]:
|
||||
await bot.send_message(chat_id=tg_id, parse_mode=ParseMode.HTML,
|
||||
await bot.send_message(chat_id=tg_id, disable_web_page_preview=True,
|
||||
text=f"<b>Напоминаю!</b>\n<i>Через {alarm[1]} минут "
|
||||
f"будет событие:</i>\n\n{message_form(0, event[3])}")
|
||||
|
||||
if daily and delta_daily1 <= time_check < delta_daily2:
|
||||
if counter:
|
||||
await bot.send_message(chat_id=tg_id, parse_mode=ParseMode.HTML,
|
||||
text=txt)
|
||||
await bot.send_message(chat_id=tg_id, disable_web_page_preview=True, text=txt)
|
||||
else:
|
||||
await bot.send_message(chat_id=tg_id, parse_mode=ParseMode.HTML,
|
||||
text=f"Сегодня событий <b>нет</b>")
|
||||
await bot.send_message(chat_id=tg_id, disable_web_page_preview=True, text=f"Сегодня событий <b>нет</b>")
|
||||
|
||||
|
||||
async def update(wait_for):
|
||||
|
|
@ -314,8 +85,20 @@ async def update(wait_for):
|
|||
os.rename(f'../data/icals/{str(user_id)}_new.ics', f'../data/icals/{str(user_id)}.ics')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.create_task(alarm(60)) # ПРОВЕРКА КАЖДУЮ 1 МИНУТУ
|
||||
loop.create_task(update(780)) # ПРОВЕРКА КАЖДУЮ 13 МИНУТУ
|
||||
executor.start_polling(dp, skip_updates=True)
|
||||
async def main() -> None:
|
||||
dp.include_router(router)
|
||||
await bot.delete_webhook(drop_pending_updates=True)
|
||||
await dp.start_polling(bot, allowed_updates=dp.resolve_used_update_types(), skipUpdates=True)
|
||||
|
||||
|
||||
async def process() -> None:
|
||||
await asyncio.gather(main(), # ЗАПУСК ОСНОВНОЙ ПРОГРАММЫ
|
||||
alarm(60), # ПРОВЕРКА КАЖДУЮ 1 МИНУТУ
|
||||
update(780)) # ПРОВЕРКА КАЖДУЮ 13 МИНУТУ
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
try: asyncio.run(process())
|
||||
except KeyboardInterrupt: pass
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
TOKEN = "**********:***************************"
|
||||
TOKEN = "**********:***************************"
|
||||
|
|
|
|||
197
code/handlers.py
Normal file
197
code/handlers.py
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
from aiogram import F, Router
|
||||
from aiogram.types import Message, CallbackQuery, ContentType, InlineKeyboardMarkup, InlineKeyboardButton, FSInputFile
|
||||
from aiogram.filters import Command
|
||||
|
||||
import wget, os
|
||||
|
||||
from init import *
|
||||
from script import *
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
# ПРИВЕТСТВЕННОЕ СООБЩЕНИЕ
|
||||
@router.message(Command('start', 'help'))
|
||||
async def helps(msg: Message) -> None:
|
||||
tg_id = int(msg.chat.id)
|
||||
if not du.user_exists(tg_id):
|
||||
du.add_user(tg_id)
|
||||
|
||||
buttons = [[InlineKeyboardButton(text="КОМАНДЫ", callback_data="com"),
|
||||
InlineKeyboardButton(text="АВТОР", callback_data="auth")]]
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=buttons, row_width=2)
|
||||
|
||||
await msg.answer(text="<b>Я.Календаркин</b> - бот для оповещения о событиях из <b>Яндекс.Календаря</b>. "
|
||||
"Для начала работы вам нужно всего лишь прислать в чат ссылку экспорта календаря в "
|
||||
"<b>формате ICal</b>. После получения ссылки, бот начнёт оповещать о всех новых событиях "
|
||||
"и появится возможность настройки оповещений. О том, какие команды есть для настройки, "
|
||||
"вы можете ознакомиться по кнопке <b>КОМАНДЫ</b>", reply_markup=keyboard)
|
||||
|
||||
|
||||
@router.callback_query(F.data == "auth")
|
||||
async def author(call: CallbackQuery) -> None:
|
||||
await call.message.answer(text='<b>| АВТОР |</b>\n\n<b>>></b> Этот бот не коммерческий проект, для упрощенного '
|
||||
'получения уведомлений о событиях в Яндекс.Календаре. Не многим этот бот будет '
|
||||
'полезен, но людям, чья работа подразумевает его использование, он станет лишь '
|
||||
'удобным инструментом. Я же пишу подобные небольшие проекты, о которых вы можете '
|
||||
'узнать больше на моём <a href="https://github.com/IGlek">GitHub</a>.')
|
||||
|
||||
|
||||
@router.callback_query(F.data == "com")
|
||||
async def commands(call: CallbackQuery) -> None:
|
||||
await call.message.answer(text='<b>| КОМАНДЫ |</b>\n\n'
|
||||
'<b>/help</b> - вспомогательная функция для уточнения работы команд\n'
|
||||
'<b>/list</b> - список событий календаря, запланированных на сегодняшний день\n'
|
||||
'<b>/notif</b> - команда, отключающая рассылку уведомлений, даже при наличии событий в календаре\n'
|
||||
'<b>/daily</b> - оповещение в 8 утра по вашему часовому поясу со списком событий на день\n'
|
||||
'<b>/moment</b> - напоминание, приходящее в момент начала события\n\n'
|
||||
'<b>/get_alarm</b> - информация о времени на которое настроены оповещения\n'
|
||||
'<b>/edit_alarm</b> - изменение времени оповещений\n'
|
||||
'<b>/stop_alarm</b> - команда, отключающая второе оповещение о событии')
|
||||
|
||||
|
||||
# КОМАНДЫ
|
||||
@router.message(Command('list'))
|
||||
async def check_list(msg: Message) -> None:
|
||||
user_id = du.get_user_id(int(msg.chat.id))
|
||||
|
||||
if du.url_exists(user_id):
|
||||
txt = "<b>Имеющиеся события на сегодня</b>\n\n"
|
||||
|
||||
lst_events = sorted(text_ical(user_id, du.get_tz(user_id)))
|
||||
today = dt_now(du.get_tz(user_id)).date()
|
||||
|
||||
counter = 0
|
||||
for event in lst_events:
|
||||
if event[0] == today:
|
||||
counter += 1
|
||||
txt += message_form(counter, event[3])
|
||||
|
||||
if counter: await msg.answer(text=txt, disable_web_page_preview=True)
|
||||
else: await msg.answer("<b>В данный момент</b> событий на сегодня найдено не было!")
|
||||
else: await msg.answer("Для отображения событий вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
@router.message(Command('notif'))
|
||||
async def notif_up(msg: Message) -> None:
|
||||
user_id = du.get_user_id(int(msg.chat.id))
|
||||
|
||||
if du.url_exists(user_id):
|
||||
if du.get_status(user_id): await msg.answer("Уведомления о событиях выключены!")
|
||||
else: await msg.answer("Уведомления о событиях включены!")
|
||||
|
||||
du.update_status(user_id)
|
||||
else: await msg.answer("Для взаимодействия с событиями вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
@router.message(Command('daily'))
|
||||
async def daily_up(msg: Message) -> None:
|
||||
user_id = du.get_user_id(int(msg.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
if dc.get_daily(user_id): await msg.answer("Ежедневные утренние уведомления выключены!")
|
||||
else: await msg.answer("Ежедневные утренние уведомления включены!")
|
||||
|
||||
dc.update_daily(user_id)
|
||||
else: await msg.answer("Для взаимодействия с событиями вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
@router.message(Command('moment'))
|
||||
async def moment_up(msg: Message) -> None:
|
||||
user_id = du.get_user_id(int(msg.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
if dc.get_start(user_id): await msg.answer("Уведомления в момент события выключены!")
|
||||
else: await msg.answer("Уведомления в момент события включены!")
|
||||
|
||||
dc.update_start(user_id)
|
||||
else: await msg.answer("Для взаимодействия с событиями вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
@router.message(Command('get_alarm'))
|
||||
async def alarm_get(msg: Message) -> None:
|
||||
user_id = du.get_user_id(int(msg.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
alarms = dc.get_alarm(user_id)
|
||||
start = dc.get_start(user_id)
|
||||
status2 = dc.get_status2(user_id)
|
||||
|
||||
txt = ""
|
||||
|
||||
if status2: txt += "<b>У вас работает два оповещения"
|
||||
else: txt += "<b>У вас работает лишь первое оповещение"
|
||||
|
||||
if start: txt += " и сообщение в момент начала события!</b>"
|
||||
else: txt += "!</b>"
|
||||
|
||||
await msg.answer(txt + f"\n\n<b>Первое оповещение</b> приходит за {alarms[0]} минут\n"
|
||||
f"<b>Второе оповещение</b> приходит за {alarms[1]} минут")
|
||||
else:
|
||||
await msg.answer("Для того, чтобы получить таймеры, вы должны прислать ical-ссылку на свой календарь!")
|
||||
|
||||
|
||||
@router.message(Command('edit_alarm'))
|
||||
async def alarm_edit(msg: Message) -> None:
|
||||
user_id = du.get_user_id(int(msg.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
await msg.answer_photo(photo=FSInputFile(path="../data/photo_edit_alarm.jpg"),
|
||||
caption="Для изменения времени вам надо в ответ на это сообщение прислать два "
|
||||
"числа через пробел: разница времени первого и второго таймера по ходу "
|
||||
"времени соответственно")
|
||||
else:
|
||||
await msg.answer("Для того, чтобы изменить таймеры, вы должны прислать ical-ссылку на свой календарь!")
|
||||
|
||||
|
||||
@router.message(Command('stop_alarm'))
|
||||
async def alarm_stop(msg: Message) -> None:
|
||||
user_id = du.get_user_id(int(msg.chat.id))
|
||||
|
||||
if dc.clock_exists(user_id):
|
||||
if dc.get_status2(user_id): await msg.answer("Второе уведомление выключено!")
|
||||
else: await msg.answer("Второе уведомление включено!")
|
||||
|
||||
dc.update_status2(user_id)
|
||||
else: await msg.answer("Для взаимодействия с событиями вы должны прислать ical-ссылку на календарь!")
|
||||
|
||||
|
||||
# ЗАГРУЗКА ССЫЛКИ
|
||||
@router.message(F.content_type == ContentType.TEXT)
|
||||
async def downloading_file_ics(msg: Message) -> None:
|
||||
user_id = du.get_user_id(int(msg.chat.id))
|
||||
|
||||
if msg.text[:5] == "https":
|
||||
try:
|
||||
wget.download(msg.text, f'../data/icals/{str(user_id)}_new.ics')
|
||||
|
||||
try: os.remove(f'../data/icals/{str(user_id)}.ics')
|
||||
except FileNotFoundError: pass
|
||||
|
||||
os.rename(f'../data/icals/{str(user_id)}_new.ics', f'../data/icals/{str(user_id)}.ics')
|
||||
|
||||
time_zone = msg.text.split("=")[-1]
|
||||
if not du.url_exists(user_id):
|
||||
du.add_url(user_id, msg.text, time_zone)
|
||||
dc.add_clock(user_id)
|
||||
else:
|
||||
du.update_url(user_id, msg.text, time_zone)
|
||||
|
||||
await msg.answer("Ссылка успешно добавлена! Уведомления уже включены!")
|
||||
except Exception:
|
||||
await msg.answer("Ошибка скачивания! Проверьте правильность ссылки и пришлите ещё раз")
|
||||
|
||||
if (msg.reply_to_message is not None) and dc.clock_exists(user_id):
|
||||
text = "Для изменения времени вам надо в ответ на это сообщение прислать два числа через " \
|
||||
"пробел: разница времени первого и второго таймера по ходу времени соответственно"
|
||||
|
||||
if msg.reply_to_message.caption == text:
|
||||
alarm_new = msg.text.split()
|
||||
|
||||
if int(alarm_new[0]) < 60 and int(alarm_new[1]) < 60:
|
||||
dc.update_alarm1(user_id, int(alarm_new[0]))
|
||||
dc.update_alarm2(user_id, int(alarm_new[1]))
|
||||
|
||||
await msg.answer("Время отправки уведомлений успешно обновлено!")
|
||||
else:
|
||||
await msg.answer("Время отправки уведомлений должно быть меньше 60 минут!")
|
||||
15
code/init.py
Normal file
15
code/init.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
from aiogram import Bot, Dispatcher
|
||||
from aiogram.enums.parse_mode import ParseMode
|
||||
from aiogram.fsm.storage.memory import MemoryStorage
|
||||
from aiogram.client.bot import DefaultBotProperties
|
||||
|
||||
from config import botToken
|
||||
|
||||
bot = Bot(token=botToken, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
dp = Dispatcher(storage=MemoryStorage())
|
||||
|
||||
|
||||
from sql import Users, Clock
|
||||
|
||||
du = Users('../db/users.db')
|
||||
dc = Clock('../db/clock.db')
|
||||
224
code/script.py
224
code/script.py
|
|
@ -1,112 +1,112 @@
|
|||
from datetime import datetime, time
|
||||
import icalendar
|
||||
|
||||
from dateutil.rrule import *
|
||||
from dateutil.parser import *
|
||||
|
||||
|
||||
def text_ical(user_id, tz):
|
||||
date = dt_now(tz)
|
||||
path = f'../data/icals/{user_id}.ics'
|
||||
|
||||
e = open(path, 'rb')
|
||||
|
||||
ecal = icalendar.Calendar.from_ical(e.read())
|
||||
events = []
|
||||
|
||||
for i, component in enumerate(ecal.walk()):
|
||||
if component.name == "VEVENT":
|
||||
|
||||
# НАЧАЛО
|
||||
dt = icalendar.vDDDTypes.to_ical(component.get('dtstart')).decode('utf-8')
|
||||
dt = dt.split("T")
|
||||
|
||||
dt_start = component.decoded("dtstart")
|
||||
dt_end = component.decoded("dtend")
|
||||
|
||||
if len(dt) == 1:
|
||||
dt_start = datetime.combine(dt_start, time(minute=1))
|
||||
dt_end = datetime.combine(dt_end, time(minute=1))
|
||||
else:
|
||||
dt_start.replace(tzinfo=None)
|
||||
dt_start = dt_start.astimezone(tz)
|
||||
|
||||
dt_end.replace(tzinfo=None)
|
||||
dt_end = dt_end.astimezone(tz)
|
||||
|
||||
# НАСТРОЙКА
|
||||
r_rule = component.get('rrule')
|
||||
if r_rule:
|
||||
list_rrule = icalendar.vRecur.to_ical(r_rule).decode('utf-8').split(';')
|
||||
|
||||
until, u_flag = [elem for elem in list_rrule if 'UNTIL' in elem], True
|
||||
list_rrule = [elem for elem in list_rrule if 'UNTIL' not in elem]
|
||||
|
||||
if until:
|
||||
until_old = until[0].split('=')[1]
|
||||
until = isoparse(until_old).replace(tzinfo=None)
|
||||
|
||||
if until.replace(tzinfo=None) <= date.replace(tzinfo=None):
|
||||
until, u_flag = "UNTIL=" + until_old, False
|
||||
|
||||
if u_flag:
|
||||
until = "UNTIL=" + "".join(date.date().isoformat().split("-")) + "T235900Z"
|
||||
|
||||
list_rrule.append(until)
|
||||
list_rrule = ";".join(list_rrule)
|
||||
|
||||
date_iso = "".join(dt_start.isoformat().split("-"))
|
||||
iso = "".join(date_iso.split(":")).split("+")[0] + "Z"
|
||||
|
||||
dates = list(map(lambda x: x.replace(tzinfo=None), list(rrulestr(list_rrule, dtstart=parse(iso)))))
|
||||
|
||||
if dates:
|
||||
dif = dt_end - dt_start
|
||||
|
||||
dt_start = dates[-1]
|
||||
dt_end = dt_start + dif
|
||||
|
||||
if date.date() == dt_start.date():
|
||||
org = component.get("organizer")
|
||||
desc = component.get("description")
|
||||
|
||||
event = {"name": component.get('summary'), "desc": desc if desc else "отсутствует",
|
||||
"org": org if org else "не назначен", "datetime": [dt_start, dt_end]}
|
||||
|
||||
events.append([dt_start.date(), dt_start.time(), i, event])
|
||||
e.close()
|
||||
|
||||
return events
|
||||
|
||||
|
||||
def message_form(k, event):
|
||||
txt = ""
|
||||
|
||||
if k:
|
||||
txt += f"-------\n"
|
||||
txt += f"<b>{k}. {event['name']}</b>\n"
|
||||
else:
|
||||
txt += f"<b>{event['name']}</b>\n"
|
||||
|
||||
txt += f"<b>Описание:</b> {event['desc']}\n"
|
||||
txt += f"<b>Организатор:</b> {event['org']}\n\n"
|
||||
txt += f"<b>Начало: {event['datetime'][0].strftime('%H:%M - %d.%m.%Y года')}</b>\n"
|
||||
txt += f"<b>Конец: {event['datetime'][1].strftime('%H:%M - %d.%m.%Y года')}</b>\n"
|
||||
|
||||
return txt
|
||||
|
||||
|
||||
def delta_time(d_event, start, end):
|
||||
d_start = datetime.combine(d_event.date(), time(hour=0, minute=start))
|
||||
d_end = datetime.combine(d_event.date(), time(hour=0, minute=end))
|
||||
|
||||
zero = datetime.combine(d_event.date(), time(0, 0, 0, 0))
|
||||
|
||||
dt_start = zero + (d_event - d_start)
|
||||
dt_end = zero + (d_event - d_end)
|
||||
|
||||
return [dt_start.time(), dt_end.time()]
|
||||
|
||||
|
||||
def dt_now(tz):
|
||||
return datetime.now(tz=tz)
|
||||
from datetime import datetime, time
|
||||
import icalendar
|
||||
|
||||
from dateutil.rrule import *
|
||||
from dateutil.parser import *
|
||||
|
||||
|
||||
def text_ical(user_id, tz):
|
||||
date = dt_now(tz)
|
||||
path = f'../data/icals/{user_id}.ics'
|
||||
|
||||
e = open(path, 'rb')
|
||||
|
||||
ecal = icalendar.Calendar.from_ical(e.read())
|
||||
events = []
|
||||
|
||||
for i, component in enumerate(ecal.walk()):
|
||||
if component.name == "VEVENT":
|
||||
|
||||
# НАЧАЛО
|
||||
dt = icalendar.vDDDTypes.to_ical(component.get('dtstart')).decode('utf-8')
|
||||
dt = dt.split("T")
|
||||
|
||||
dt_start = component.decoded("dtstart")
|
||||
dt_end = component.decoded("dtend")
|
||||
|
||||
if len(dt) == 1:
|
||||
dt_start = datetime.combine(dt_start, time(minute=1))
|
||||
dt_end = datetime.combine(dt_end, time(minute=1))
|
||||
else:
|
||||
dt_start.replace(tzinfo=None)
|
||||
dt_start = dt_start.astimezone(tz)
|
||||
|
||||
dt_end.replace(tzinfo=None)
|
||||
dt_end = dt_end.astimezone(tz)
|
||||
|
||||
# НАСТРОЙКА
|
||||
r_rule = component.get('rrule')
|
||||
if r_rule:
|
||||
list_rrule = icalendar.vRecur.to_ical(r_rule).decode('utf-8').split(';')
|
||||
|
||||
until, u_flag = [elem for elem in list_rrule if 'UNTIL' in elem], True
|
||||
list_rrule = [elem for elem in list_rrule if 'UNTIL' not in elem]
|
||||
|
||||
if until:
|
||||
until_old = until[0].split('=')[1]
|
||||
until = isoparse(until_old).replace(tzinfo=None)
|
||||
|
||||
if until.replace(tzinfo=None) <= date.replace(tzinfo=None):
|
||||
until, u_flag = "UNTIL=" + until_old, False
|
||||
|
||||
if u_flag:
|
||||
until = "UNTIL=" + "".join(date.date().isoformat().split("-")) + "T235900Z"
|
||||
|
||||
list_rrule.append(until)
|
||||
list_rrule = ";".join(list_rrule)
|
||||
|
||||
date_iso = "".join(dt_start.isoformat().split("-"))
|
||||
iso = "".join(date_iso.split(":")).split("+")[0] + "Z"
|
||||
|
||||
dates = list(map(lambda x: x.replace(tzinfo=None), list(rrulestr(list_rrule, dtstart=parse(iso)))))
|
||||
|
||||
if dates:
|
||||
dif = dt_end - dt_start
|
||||
|
||||
dt_start = dates[-1]
|
||||
dt_end = dt_start + dif
|
||||
|
||||
if date.date() == dt_start.date():
|
||||
org = component.get("organizer")
|
||||
desc = component.get("description")
|
||||
|
||||
event = {"name": component.get('summary'), "desc": desc if desc else "отсутствует",
|
||||
"org": org if org else "не назначен", "datetime": [dt_start, dt_end]}
|
||||
|
||||
events.append([dt_start.date(), dt_start.time(), i, event])
|
||||
e.close()
|
||||
|
||||
return events
|
||||
|
||||
|
||||
def message_form(k, event):
|
||||
txt = ""
|
||||
|
||||
if k:
|
||||
txt += f"-------\n"
|
||||
txt += f"<b>{k}. {event['name']}</b>\n"
|
||||
else:
|
||||
txt += f"<b>{event['name']}</b>\n"
|
||||
|
||||
txt += f"<b>Описание:</b> {event['desc']}\n"
|
||||
txt += f"<b>Организатор:</b> {event['org']}\n\n"
|
||||
txt += f"<b>Начало: {event['datetime'][0].strftime('%H:%M - %d.%m.%Y года')}</b>\n"
|
||||
txt += f"<b>Конец: {event['datetime'][1].strftime('%H:%M - %d.%m.%Y года')}</b>\n"
|
||||
|
||||
return txt
|
||||
|
||||
|
||||
def delta_time(d_event, start, end):
|
||||
d_start = datetime.combine(d_event.date(), time(hour=0, minute=start))
|
||||
d_end = datetime.combine(d_event.date(), time(hour=0, minute=end))
|
||||
|
||||
zero = datetime.combine(d_event.date(), time(0, 0, 0, 0))
|
||||
|
||||
dt_start = zero + (d_event - d_start)
|
||||
dt_end = zero + (d_event - d_end)
|
||||
|
||||
return [dt_start.time(), dt_end.time()]
|
||||
|
||||
|
||||
def dt_now(tz):
|
||||
return datetime.now(tz=tz)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue