patch 5b2c938f7967a3345435fe21b2127999d0975f50 Author: E. Bosch Date: Mon Jun 26 00:17:22 CEST 2023 * Add exclam module to handle channel/chat commands begining with exclamation mark (!) Implement reply (!re) as first exclam command diff -rN -u old-irgramd/exclam.py new-irgramd/exclam.py --- old-irgramd/exclam.py 1970-01-01 01:00:00.000000000 +0100 +++ new-irgramd/exclam.py 2024-11-22 21:58:16.780737350 +0100 @@ -0,0 +1,49 @@ +# irgramd: IRC-Telegram gateway +# exclam.py: IRC exclamation command handlers +# +# Copyright (c) 2023 E. Bosch +# +# Use of this source code is governed by a MIT style license that +# can be found in the LICENSE file included in this project. + +from utils import command, HELP + +class exclam(command): + def __init__(self, telegram): + self.commands = \ + { # Command Handler Arguments Min Max Maxsplit + '!re': (self.handle_command_re, 2, 2, 2), + } + self.tg = telegram + self.irc = telegram.irc + self.tmp_ircnick = None + self.tmp_telegram_id = None + self.tmp_tg_msg = None + + async def command(self, message, telegram_id, user): + self.tmp_telegram_id = telegram_id + res = await self.parse_command(message, nick=None) + if isinstance(res, tuple): + await self.irc.send_msg(self.irc.service_user, None, res[0], user) + res = False + return res, self.tmp_tg_msg + + async def handle_command_re(self, cid=None, msg=None, help=None): + if not help: + id = self.tg.mid.id_to_num_offset(self.tmp_telegram_id, cid) + chk_msg = await self.tg.telegram_client.get_messages(entity=self.tmp_telegram_id, ids=id) + if chk_msg is not None: + self.tmp_tg_msg = await self.tg.telegram_client.send_message(self.tmp_telegram_id, msg, reply_to=id) + reply = True + else: + reply = ('Unknown message to reply',) + else: # HELP.brief or HELP.desc (first line) + reply = (' !re Reply to a message',) + if help == HELP.desc: # rest of HELP.desc + reply += \ + ( + ' !re ', + 'Reply with to a message with on current', + 'channel/chat.' + ) + return reply diff -rN -u old-irgramd/irc.py new-irgramd/irc.py --- old-irgramd/irc.py 2024-11-22 21:58:16.780737350 +0100 +++ new-irgramd/irc.py 2024-11-22 21:58:16.780737350 +0100 @@ -22,6 +22,7 @@ from irc_replies import irc_codes from utils import chunks, set_replace, split_lines from service import service +from exclam import exclam # Constants @@ -109,6 +110,7 @@ def set_telegram(self, tg): self.tg = tg self.service = service(self.conf, self.tg) + self.exclam = exclam(self.tg) # IRC @@ -408,14 +410,18 @@ if tgt in self.iid_to_tid: message = self.tg.replace_mentions(message, me_nick='', received=False) telegram_id = self.iid_to_tid[tgt] - tg_msg = await self.tg.telegram_client.send_message(telegram_id, message) - - mid = self.tg.mid.num_to_id_offset(telegram_id, tg_msg.id) - text = '[{}] {}'.format(mid, message) - self.tg.to_cache(tg_msg.id, mid, text, message, user, chan, media=None) + if message[0] == '!': + cont, tg_msg = await self.exclam.command(message, telegram_id, user) + else: + tg_msg = await self.tg.telegram_client.send_message(telegram_id, message) + cont = True + if cont: + mid = self.tg.mid.num_to_id_offset(telegram_id, tg_msg.id) + text = '[{}] {}'.format(mid, message) + self.tg.to_cache(tg_msg.id, mid, text, message, user, chan, media=None) - if defered_send: - await defered_send(user, defered_target, text) + if defered_send: + await defered_send(user, defered_target, text) else: await self.reply_code(user, 'ERR_NOSUCHNICK', (target,)) diff -rN -u old-irgramd/service.py new-irgramd/service.py --- old-irgramd/service.py 2024-11-22 21:58:16.780737350 +0100 +++ new-irgramd/service.py 2024-11-22 21:58:16.784737343 +0100 @@ -6,19 +6,19 @@ # Use of this source code is governed by a MIT style license that # can be found in the LICENSE file included in this project. -from utils import compact_date, command +from utils import compact_date, command, HELP from telethon import utils as tgutils class service(command): def __init__(self, settings, telegram): self.commands = \ - { # Command Handler Arguments Min Max - 'code': (self.handle_command_code, 1, 1), - 'dialog': (self.handle_command_dialog, 1, 2), - 'get': (self.handle_command_get, 2, 2), - 'help': (self.handle_command_help, 0, 1), - 'history': (self.handle_command_history, 1, 3), - 'mark_read': (self.handle_command_mark_read, 1, 1), + { # Command Handler Arguments Min Max Maxsplit + 'code': (self.handle_command_code, 1, 1, -1), + 'dialog': (self.handle_command_dialog, 1, 2, -1), + 'get': (self.handle_command_get, 2, 2, -1), + 'help': (self.handle_command_help, 0, 1, -1), + 'history': (self.handle_command_history, 1, 3, -1), + 'mark_read': (self.handle_command_mark_read, 1, 1, -1), } self.ask_code = settings['ask_code'] self.tg = telegram @@ -144,12 +144,20 @@ help_text += await handler(help=HELP.brief) help_text += \ ( + 'The commands begining with ! (exclamation) must be used directly', + 'in channels or chats. The following ! commands are available:', + ) + for command in self.irc.exclam.commands.values(): + handler = command[0] + help_text += await handler(help=HELP.brief) + help_text += \ + ( 'If you need more information about a specific command you can use', 'help ', ) help_text += end_help - elif help_command in self.commands.keys(): - handler = self.commands[help_command][0] + elif help_command in (all_commands := dict(**self.commands, **self.irc.exclam.commands)).keys(): + handler = all_commands[help_command][0] help_text = start_help help_text += await handler(help=HELP.desc) help_text += end_help @@ -250,7 +258,3 @@ peer_id = None reply = ('Unknown user or channel',) return peer_id, reply - -class HELP: - desc = 1 - brief = 2 diff -rN -u old-irgramd/utils.py new-irgramd/utils.py --- old-irgramd/utils.py 2024-11-22 21:58:16.780737350 +0100 +++ new-irgramd/utils.py 2024-11-22 21:58:16.784737343 +0100 @@ -23,11 +23,11 @@ class command: async def parse_command(self, line, nick): - words = line.split() - command = words.pop(0).lower() + command = line.partition(' ')[0].lower() self.tmp_ircnick = nick if command in self.commands.keys(): - handler, min_args, max_args = self.commands[command] + handler, min_args, max_args, maxsplit = self.commands[command] + words = line.split(maxsplit=maxsplit)[1:] num_words = len(words) if num_words < min_args or num_words > max_args: reply = ('Wrong number of arguments',) @@ -38,6 +38,10 @@ return reply +class HELP: + desc = 1 + brief = 2 + def chunks(iterable, n, fillvalue=None): ''' Return iterable consisting of a sequence of n-length chunks ''' args = [iter(iterable)] * n