From 77b61f4c61d33cadd1b6331f5933c8c93995aed9 Mon Sep 17 00:00:00 2001 From: Johnny Gear Date: Thu, 13 Nov 2025 22:03:20 -0600 Subject: [PATCH] Telegram - /skip_day --- main.py | 2 ++ settings.py | 2 +- telegram.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 51ac8ca..e0b97ba 100644 --- a/main.py +++ b/main.py @@ -5,6 +5,7 @@ import asyncio from scheduling import OrderScheduler from orders import order_issue, order_check +from telegram import handle_commands logger = logging.getLogger(__name__) @@ -36,4 +37,5 @@ if __name__=='__main__': else: loop = asyncio.new_event_loop() s = OrderScheduler(loop) + loop.run_until_complete(handle_commands()) loop.run_forever() diff --git a/settings.py b/settings.py index b521324..c2a3e50 100644 --- a/settings.py +++ b/settings.py @@ -11,7 +11,7 @@ MASTODON_INSTANCE = os.environ.get("MASTODON_INSTANCE") MASTODON_ACCESS_TOKEN = os.environ.get('MASTODON_ACCESS_TOKEN') TELEGRAM_API_TOKEN = os.environ.get('TELEGRAM_API_TOKEN') -TELEGRAM_CHAT_ID = os.environ.get('TELEGRAM_CHAT_ID') +TELEGRAM_CHAT_ID = int(os.environ.get('TELEGRAM_CHAT_ID')) SQLITE_DB = os.environ.get('SQLITE_DB', 'db.sqlite3') diff --git a/telegram.py b/telegram.py index dae3523..2d9a7b7 100644 --- a/telegram.py +++ b/telegram.py @@ -1,7 +1,10 @@ -import json +import re import logging +import asyncio from settings import TELEGRAM_API_TOKEN, TELEGRAM_CHAT_ID +from db import Database +from util import make_session logger = logging.getLogger(__name__) @@ -14,6 +17,18 @@ class Telegram: self.aiosession = aiosession + async def get(self, request, params): + async with self.aiosession.get('{}{}/{}'.format( + TELEGRAM_API_URL, + TELEGRAM_API_TOKEN, + request + ), params=params) as response: + if not response.ok: + logger.error('{} {}'.format(request, response.status)) + raise Exception('{} {}'.format(request, response.status)) + + return await response.json() + async def post(self, request, data): async with self.aiosession.post('{}{}/{}'.format( TELEGRAM_API_URL, @@ -33,3 +48,85 @@ class Telegram: } return await self.post('sendMessage', data=data) + + async def updates_get(self, offset=0, timeout=240): + return await self.get('getUpdates', params={ + 'offset': offset, + 'timeout': timeout + }) + +class TelegramCommand(): + command_regex = None + command_text = None + authorized = True + + def matches(self, text): + return ( + (self.command_text is not None and text.startswith(self.command_text)) or + (self.command_regex is not None and self.command_regex.match(text) is not None) + ) + + async def exec(self, text, update, session): + pass + +class SkipDayAddCommand(TelegramCommand): + command_regex = re.compile(r"^\/skip_day( (?P\d{4}-\d{2}-\d{2}))?$") + + async def exec(self, text, update, session): + date_str = text.split(' ')[1] + + db = Database() + db.skip_day_put(date_str) + + yield f"Added skip day {date_str}" + +commands = [ + SkipDayAddCommand() +] + +async def do_reply(data, t): + if(type(data) is str): + await t.message_send( + data + ) + +async def handle_commands(commands=commands): + async with make_session() as session: + t = Telegram(session) + + offset = 0 + while True: + try: + updates = await t.updates_get(offset=offset) + + if(updates['ok']): + for update in updates['result']: + if('message' in update): + chat_id = update['message']['chat']['id'] + + if(chat_id != TELEGRAM_CHAT_ID): + continue + + for command in commands: + if(command.matches(update['message']['text'])): + try: + result = command.exec(update['message']['text'], update, session) + + if result.__class__.__name__ == 'async_generator': + async for r in result: + await do_reply(r, t) + else: + await do_reply(await result, t) + except: + await t.message_send('There was a problem with your command') + logger.exception('Problem while executing a command') + + break + offset = update['update_id'] + 1 + else: + logger.warning("getUpdates was not ok {}".format(update)) + await asyncio.sleep(30) + except Exception as e: + logger.exception("getUpdates exception {}".format(e)) + await asyncio.sleep(30) +