exclam: Add upload (!upl) command to upload files/media to chats/channels
Annotate for file /telegram.py
2022-02-20 E. 1 # irgramd: IRC-Telegram gateway
01:25:27 ' 2 # telegram.py: Interface to Telethon Telegram library
' 3 #
' 4 # Copyright (c) 2019 Peter Bui <pbui@bx612.space>
2024-04-07 E. 5 # Copyright (c) 2020-2024 E. Bosch <presidev@AT@gmail.com>
2022-02-20 E. 6 #
01:25:27 ' 7 # Use of this source code is governed by a MIT style license that
' 8 # can be found in the LICENSE file included in this project.
2020-11-21 E. 9
01:12:30 ' 10 import logging
' 11 import os
2021-02-07 E. 12 import datetime
2021-02-12 E. 13 import re
2022-02-16 E. 14 import aioconsole
2022-03-19 E. 15 import asyncio
2023-04-08 E. 16 import collections
2020-11-21 E. 17 import telethon
2023-03-22 E. 18 from telethon import types as tgty, utils as tgutils
2023-04-25 E. 19 from telethon.tl.functions.messages import GetMessagesReactionsRequest
2020-11-21 E. 20
2021-01-27 E. 21 # Local modules
19:51:33 ' 22
' 23 from include import CHAN_MAX_LENGHT, NICK_MAX_LENGTH
2021-01-31 E. 24 from irc import IRCUser
2023-12-17 E. 25 from utils import sanitize_filename, add_filename, is_url_equiv, extract_url, get_human_size, get_human_duration, get_highlighted, fix_braces, format_timestamp
2023-04-29 E. 26 import emoji2emoticon as e
2020-11-21 E. 27
2022-02-22 E. 28 # Test IP table
01:37:33 ' 29
' 30 TEST_IPS = { 1: '149.154.175.10',
' 31 2: '149.154.167.40',
' 32 3: '149.154.175.117'
' 33 }
' 34
2020-11-21 E. 35 # Telegram
01:12:30 ' 36
' 37 class TelegramHandler(object):
2021-12-12 E. 38 def __init__(self, irc, settings):
2020-11-21 E. 39 self.logger = logging.getLogger()
2021-12-12 E. 40 self.config_dir = settings['config_dir']
2024-04-14 E. 41 self.cache_dir = settings['cache_dir']
2023-10-15 E. 42 self.download = settings['download_media']
2023-10-15 E. 43 self.notice_size = settings['download_notice'] * 1048576
2023-06-05 E. 44 self.media_dir = settings['media_dir']
2022-01-30 E. 45 self.media_url = settings['media_url']
2024-04-14 E. 46 self.upload_dir = settings['upload_dir']
2022-02-16 E. 47 self.api_id = settings['api_id']
01:18:10 ' 48 self.api_hash = settings['api_hash']
2022-02-16 E. 49 self.phone = settings['phone']
2022-02-22 E. 50 self.test = settings['test']
01:37:33 ' 51 self.test_dc = settings['test_datacenter']
' 52 self.test_ip = settings['test_host'] if settings['test_host'] else TEST_IPS[self.test_dc]
' 53 self.test_port = settings['test_port']
2022-03-08 E. 54 self.ask_code = settings['ask_code']
2023-04-26 E. 55 self.quote_len = settings['quote_length']
2023-05-06 E. 56 self.hist_fmt = settings['hist_timestamp_format']
23:31:34 ' 57 self.timezone = settings['timezone']
2023-07-20 E. 58 self.geo_url = settings['geo_url']
2023-04-29 E. 59 if not settings['emoji_ascii']:
18:47:52 ' 60 e.emo = {}
2022-01-30 E. 61 self.media_cn = 0
2020-11-21 E. 62 self.irc = irc
2021-01-27 E. 63 self.authorized = False
2021-02-02 E. 64 self.id = None
22:52:41 ' 65 self.tg_username = None
2021-02-12 E. 66 self.channels_date = {}
2022-01-26 E. 67 self.mid = mesg_id('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%+./_~')
2022-02-08 E. 68 self.webpending = {}
2023-03-28 E. 69 self.refwd_me = False
2023-04-08 E. 70 self.cache = collections.OrderedDict()
2023-07-07 E. 71 self.sorted_len_usernames = []
2022-03-19 E. 72 # Set event to be waited by irc.check_telegram_auth()
05:11:26 ' 73 self.auth_checked = asyncio.Event()
2021-01-27 E. 74
23:13:48 ' 75 async def initialize_telegram(self):
2020-11-21 E. 76 # Setup media folder
2024-04-14 E. 77 self.telegram_media_dir = os.path.expanduser(self.media_dir or os.path.join(self.cache_dir, 'media'))
2020-11-21 E. 78 if not os.path.exists(self.telegram_media_dir):
01:12:30 ' 79 os.makedirs(self.telegram_media_dir)
' 80
2024-04-14 E. 81 # Setup upload folder
20:48:30 ' 82 self.telegram_upload_dir = os.path.expanduser(self.upload_dir or os.path.join(self.cache_dir, 'upload'))
' 83 if not os.path.exists(self.telegram_upload_dir):
' 84 os.makedirs(self.telegram_upload_dir)
' 85
2020-11-21 E. 86 # Setup session folder
01:12:30 ' 87 self.telegram_session_dir = os.path.join(self.config_dir, 'session')
' 88 if not os.path.exists(self.telegram_session_dir):
' 89 os.makedirs(self.telegram_session_dir)
' 90
' 91 # Construct Telegram client
2022-02-22 E. 92 if self.test:
01:37:33 ' 93 self.telegram_client = telethon.TelegramClient(None, self.api_id, self.api_hash)
' 94 self.telegram_client.session.set_dc(self.test_dc, self.test_ip, self.test_port)
' 95 else:
' 96 telegram_session = os.path.join(self.telegram_session_dir, 'telegram')
' 97 self.telegram_client = telethon.TelegramClient(telegram_session, self.api_id, self.api_hash)
2020-11-21 E. 98
01:12:30 ' 99 # Initialize Telegram ID to IRC nick mapping
' 100 self.tid_to_iid = {}
' 101
' 102 # Register Telegram callbacks
' 103 callbacks = (
' 104 (self.handle_telegram_message , telethon.events.NewMessage),
2022-02-08 E. 105 (self.handle_raw, telethon.events.Raw),
2020-11-21 E. 106 (self.handle_telegram_chat_action, telethon.events.ChatAction),
2023-04-10 E. 107 (self.handle_telegram_deleted , telethon.events.MessageDeleted),
2023-04-15 E. 108 (self.handle_telegram_edited, telethon.events.MessageEdited),
2020-11-21 E. 109 )
01:12:30 ' 110 for handler, event in callbacks:
' 111 self.telegram_client.add_event_handler(handler, event)
' 112
' 113 # Start Telegram client
2022-02-22 E. 114 if self.test:
01:37:33 ' 115 await self.telegram_client.start(self.phone, code_callback=lambda: str(self.test_dc) * 5)
' 116 else:
' 117 await self.telegram_client.connect()
2021-01-27 E. 118
2022-02-16 E. 119 while not await self.telegram_client.is_user_authorized():
2022-03-08 E. 120 self.logger.info('Telegram account not authorized')
2022-02-16 E. 121 await self.telegram_client.send_code_request(self.phone)
2022-03-19 E. 122 self.auth_checked.set()
2022-03-08 E. 123 if not self.ask_code:
21:58:55 ' 124 return
' 125 self.logger.info('You must provide the Login code that Telegram will '
' 126 'sent you via SMS or another connected client')
2022-02-16 E. 127 code = await aioconsole.ainput('Login code: ')
22:22:04 ' 128 try:
' 129 await self.telegram_client.sign_in(code=code)
' 130 except:
' 131 pass
' 132
2022-03-08 E. 133 await self.continue_auth()
21:58:55 ' 134
' 135 async def continue_auth(self):
2022-02-16 E. 136 self.logger.info('Telegram account authorized')
22:22:04 ' 137 self.authorized = True
2022-03-19 E. 138 self.auth_checked.set()
2022-02-16 E. 139 await self.init_mapping()
2021-01-27 E. 140
23:13:48 ' 141 async def init_mapping(self):
2020-11-21 E. 142 # Update IRC <-> Telegram mapping
2021-02-02 E. 143 tg_user = await self.telegram_client.get_me()
22:52:41 ' 144 self.id = tg_user.id
' 145 self.tg_username = self.get_telegram_nick(tg_user)
2023-07-07 E. 146 self.add_sorted_len_usernames(self.tg_username)
2022-02-19 E. 147 self.set_ircuser_from_telegram(tg_user)
2021-01-27 E. 148 async for dialog in self.telegram_client.iter_dialogs():
2020-11-22 E. 149 chat = dialog.entity
2021-02-01 E. 150 if isinstance(chat, tgty.User):
2021-02-02 E. 151 self.set_ircuser_from_telegram(chat)
2020-11-22 E. 152 else:
2021-01-31 E. 153 await self.set_irc_channel_from_telegram(chat)
19:23:45 ' 154
' 155 def set_ircuser_from_telegram(self, user):
' 156 if user.id not in self.tid_to_iid:
' 157 tg_nick = self.get_telegram_nick(user)
2021-02-02 E. 158 tg_ni = tg_nick.lower()
22:52:41 ' 159 if not user.is_self:
2023-06-14 E. 160 irc_user = IRCUser(None, ('Telegram',''), tg_nick, user.id, self.get_telegram_display_name(user))
2021-02-02 E. 161 self.irc.users[tg_ni] = irc_user
2023-07-07 E. 162 self.add_sorted_len_usernames(tg_ni)
2021-01-31 E. 163 self.tid_to_iid[user.id] = tg_nick
2021-02-02 E. 164 self.irc.iid_to_tid[tg_ni] = user.id
2021-01-31 E. 165 else:
19:23:45 ' 166 tg_nick = self.tid_to_iid[user.id]
' 167 return tg_nick
' 168
' 169 async def set_irc_channel_from_telegram(self, chat):
' 170 channel = self.get_telegram_channel(chat)
2023-03-17 E. 171 self.tid_to_iid[chat.id] = channel
2021-02-01 E. 172 chan = channel.lower()
2023-03-17 E. 173 self.irc.iid_to_tid[chan] = chat.id
2023-03-18 E. 174 self.irc.irc_channels[chan] = set()
2021-01-31 E. 175 # Add users from the channel
2021-02-01 E. 176 async for user in self.telegram_client.iter_participants(chat.id):
2021-01-31 E. 177 user_nick = self.set_ircuser_from_telegram(user)
2021-02-01 E. 178 if not user.is_self:
22:18:25 ' 179 self.irc.irc_channels[chan].add(user_nick)
' 180 # Add admin users as ops in irc
' 181 if isinstance(user.participant, tgty.ChatParticipantAdmin):
' 182 self.irc.irc_channels_ops[chan].add(user_nick)
' 183 # Add creator users as founders in irc
' 184 elif isinstance(user.participant, tgty.ChatParticipantCreator):
2021-02-04 E. 185 self.irc.irc_channels_founder[chan].add(user_nick)
2020-11-21 E. 186
01:12:30 ' 187 def get_telegram_nick(self, user):
' 188 nick = (user.username
2021-01-31 E. 189 or self.get_telegram_display_name(user)
2020-11-21 E. 190 or str(user.id))
2021-01-31 E. 191 nick = nick[:NICK_MAX_LENGTH]
2020-11-21 E. 192 while nick in self.irc.iid_to_tid:
01:12:30 ' 193 nick += '_'
' 194 return nick
2021-01-31 E. 195
19:23:45 ' 196 def get_telegram_display_name(self, user):
' 197 name = telethon.utils.get_display_name(user)
' 198 name = name.replace(' ', '_')
' 199 return name
2020-11-21 E. 200
2022-02-05 E. 201 async def get_telegram_display_name_me(self):
02:30:31 ' 202 tg_user = await self.telegram_client.get_me()
' 203 return self.get_telegram_display_name(tg_user)
' 204
2020-11-21 E. 205 def get_telegram_channel(self, chat):
2023-03-18 E. 206 chan = '#' + chat.title.replace(' ', '-').replace(',', '-')
03:43:35 ' 207 while chan.lower() in self.irc.iid_to_tid:
' 208 chan += '_'
' 209 return chan
2020-11-21 E. 210
2021-02-01 E. 211 def get_irc_user_from_telegram(self, tid):
18:48:42 ' 212 nick = self.tid_to_iid[tid]
2021-02-02 E. 213 if nick == self.tg_username: return None
2021-02-01 E. 214 return self.irc.users[nick.lower()]
18:48:42 ' 215
2023-12-02 E. 216 def get_irc_name_from_telegram_id(self, tid):
19:41:44 ' 217 if tid in self.tid_to_iid.keys():
' 218 name_in_irc = self.tid_to_iid[tid]
' 219 else:
' 220 name_in_irc = '<Unknown>'
' 221 return name_in_irc
' 222
2023-06-07 E. 223 async def get_irc_name_from_telegram_forward(self, fwd, saved):
22:26:21 ' 224 from_id = fwd.saved_from_peer if saved else fwd.from_id
' 225 if from_id is None:
2023-04-29 E. 226 # telegram user has privacy options to show only the name
2023-06-07 E. 227 # or was a broadcast from a channel (no user)
22:26:21 ' 228 name = fwd.from_name
2023-04-29 E. 229 else:
2023-06-07 E. 230 peer_id, type = self.get_peer_id_and_type(from_id)
22:26:21 ' 231 if type == 'user':
2023-06-23 E. 232 try:
21:49:58 ' 233 user = self.get_irc_user_from_telegram(peer_id)
' 234 except:
' 235 name = str(peer_id)
2023-06-07 E. 236 else:
2023-06-23 E. 237 if user is None:
21:49:58 ' 238 name = '{}'
' 239 self.refwd_me = True
' 240 else:
' 241 name = user.irc_nick
2023-04-29 E. 242 else:
2023-06-07 E. 243 try:
22:26:21 ' 244 name = await self.get_irc_channel_from_telegram_id(peer_id)
' 245 except:
' 246 name = ''
' 247 return name
2023-04-29 E. 248
2020-11-21 E. 249 async def get_irc_nick_from_telegram_id(self, tid, entity=None):
01:12:30 ' 250 if tid not in self.tid_to_iid:
' 251 user = entity or await self.telegram_client.get_entity(tid)
' 252 nick = self.get_telegram_nick(user)
' 253 self.tid_to_iid[tid] = nick
' 254 self.irc.iid_to_tid[nick] = tid
' 255
' 256 return self.tid_to_iid[tid]
' 257
' 258 async def get_irc_channel_from_telegram_id(self, tid, entity=None):
2023-03-22 E. 259 rtid, type = tgutils.resolve_id(tid)
21:15:41 ' 260 if rtid not in self.tid_to_iid:
2020-11-21 E. 261 chat = entity or await self.telegram_client.get_entity(tid)
01:12:30 ' 262 channel = self.get_telegram_channel(chat)
2023-03-22 E. 263 self.tid_to_iid[rtid] = channel
21:15:41 ' 264 self.irc.iid_to_tid[channel] = rtid
' 265
' 266 return self.tid_to_iid[rtid]
2020-11-21 E. 267
01:12:30 ' 268 async def get_telegram_channel_participants(self, tid):
' 269 channel = self.tid_to_iid[tid]
' 270 nicks = []
' 271 async for user in self.telegram_client.iter_participants(tid):
' 272 user_nick = await self.get_irc_nick_from_telegram_id(user.id, user)
' 273
' 274 nicks.append(user_nick)
' 275 self.irc.irc_channels[channel].add(user_nick)
' 276
2020-11-24 E. 277 return nicks
2020-11-21 E. 278
2021-02-07 E. 279 async def get_telegram_idle(self, irc_nick, tid=None):
2022-02-26 E. 280 if self.irc.users[irc_nick].is_service:
23:47:48 ' 281 return None
2021-02-07 E. 282 tid = self.get_tid(irc_nick, tid)
02:14:36 ' 283 user = await self.telegram_client.get_entity(tid)
' 284 if isinstance(user.status,tgty.UserStatusRecently) or \
' 285 isinstance(user.status,tgty.UserStatusOnline):
' 286 idle = 0
' 287 elif isinstance(user.status,tgty.UserStatusOffline):
' 288 last = user.status.was_online
' 289 current = datetime.datetime.now(datetime.timezone.utc)
' 290 idle = int((current - last).total_seconds())
' 291 elif isinstance(user.status,tgty.UserStatusLastWeek):
' 292 idle = 604800
' 293 elif isinstance(user.status,tgty.UserStatusLastMonth):
' 294 idle = 2678400
' 295 else:
' 296 idle = None
' 297 return idle
' 298
2022-01-30 E. 299 async def get_channel_topic(self, channel, entity_cache):
2021-02-12 E. 300 tid = self.get_tid(channel)
2022-01-30 E. 301 # entity_cache should be a list to be a persistent and by reference value
2021-02-12 E. 302 if entity_cache[0]:
02:09:58 ' 303 entity = entity_cache[0]
' 304 else:
' 305 entity = await self.telegram_client.get_entity(tid)
' 306 entity_cache[0] = entity
2023-04-11 E. 307 entity_type = self.get_entity_type(entity, format='long')
2021-02-12 E. 308 return 'Telegram ' + entity_type + ' ' + str(tid) + ': ' + entity.title
02:09:58 ' 309
2022-01-30 E. 310 async def get_channel_creation(self, channel, entity_cache):
2021-02-12 E. 311 tid = self.get_tid(channel)
02:09:58 ' 312 if tid in self.channels_date.keys():
' 313 timestamp = self.channels_date[tid]
' 314 else:
2022-01-30 E. 315 # entity_cache should be a list to be a persistent and by reference value
2021-02-12 E. 316 if entity_cache[0]:
02:09:58 ' 317 entity = entity_cache[0]
' 318 else:
' 319 entity = await self.telegram_client.get_entity(tid)
' 320 entity_cache[0] = entity
' 321 timestamp = entity.date.timestamp()
' 322 self.channels_date[tid] = timestamp
' 323 return int(timestamp)
' 324
' 325 def get_tid(self, irc_item, tid=None):
' 326 it = irc_item.lower()
2021-02-07 E. 327 if tid:
02:14:36 ' 328 pass
2021-02-12 E. 329 elif it in self.irc.iid_to_tid:
02:09:58 ' 330 tid = self.irc.iid_to_tid[it]
2021-02-07 E. 331 else:
02:14:36 ' 332 tid = self.id
' 333 return tid
' 334
2023-04-11 E. 335 def get_entity_type(self, entity, format):
22:43:22 ' 336 if isinstance(entity, tgty.User):
' 337 short = long = 'User'
' 338 elif isinstance(entity, tgty.Chat):
' 339 short = 'Chat'
' 340 long = 'Chat/Basic Group'
' 341 elif isinstance(entity, tgty.Channel):
' 342 if entity.broadcast:
' 343 short = 'Broad'
' 344 long = 'Broadcast Channel'
' 345 elif entity.megagroup:
' 346 short = 'Mega'
' 347 long = 'Super/Megagroup Channel'
' 348 elif entity.gigagroup:
' 349 short = 'Giga'
' 350 long = 'Broadcast Gigagroup Channel'
' 351
' 352 return short if format == 'short' else long
2021-02-12 E. 353
2023-06-07 E. 354 def get_peer_id_and_type(self, peer):
22:26:21 ' 355 if isinstance(peer, tgty.PeerChannel):
' 356 id = peer.channel_id
' 357 type = 'chan'
' 358 elif isinstance(peer, tgty.PeerChat):
' 359 id = peer.chat_id
' 360 type = 'chan'
' 361 elif isinstance(peer, tgty.PeerUser):
' 362 id = peer.user_id
' 363 type = 'user'
' 364 else:
' 365 id = peer
' 366 type = ''
' 367 return id, type
' 368
2023-04-19 E. 369 async def is_bot(self, irc_nick, tid=None):
23:49:15 ' 370 user = self.irc.users[irc_nick]
' 371 if user.stream or user.is_service:
' 372 bot = False
' 373 else:
' 374 bot = user.bot
' 375 if bot == None:
' 376 tid = self.get_tid(irc_nick, tid)
' 377 tg_user = await self.telegram_client.get_entity(tid)
' 378 bot = tg_user.bot
' 379 user.bot = bot
' 380 return bot
' 381
2023-04-25 E. 382 async def edition_case(self, msg):
20:34:42 ' 383 def msg_edited(m):
' 384 return m.id in self.cache and \
' 385 ( m.message != self.cache[m.id]['text']
' 386 or m.media != self.cache[m.id]['media']
' 387 )
' 388 async def get_reactions(m):
' 389 react = await self.telegram_client(GetMessagesReactionsRequest(m.peer_id, id=[m.id]))
' 390 return react.updates[0].reactions.recent_reactions
' 391
' 392 react = None
' 393 if msg.reactions is None:
' 394 case = 'edition'
' 395 elif (reactions := await get_reactions(msg)) is None:
' 396 if msg_edited(msg):
' 397 case = 'edition'
' 398 else:
' 399 case = 'react-del'
' 400 elif react := next((x for x in reactions if x.date == msg.edit_date), None):
' 401 case = 'react-add'
' 402 else:
' 403 if msg_edited(msg):
' 404 case = 'edition'
' 405 else:
' 406 case = 'react-del'
' 407 react = None
' 408 return case, react
' 409
' 410 def to_cache(self, id, mid, message, proc_message, user, chan, media):
2023-04-08 E. 411 if len(self.cache) >= 10000:
10:30:10 ' 412 self.cache.popitem(last=False)
' 413 self.cache[id] = {
' 414 'mid': mid,
2023-04-15 E. 415 'text': message,
23:13:07 ' 416 'rendered_text': proc_message,
2023-04-08 E. 417 'user': user,
2023-04-25 E. 418 'channel': chan,
20:34:42 ' 419 'media': media
2023-04-08 E. 420 }
10:30:10 ' 421
2023-06-15 E. 422 def replace_mentions(self, text, me_nick='', received=True):
18:08:03 ' 423 # For received replace @mention to ~mention~
' 424 # For sent replace mention: to @mention
' 425 rargs = {}
2023-07-07 E. 426 def repl_mentioned(text, me_nick, received, mark, repl_pref, repl_suff):
23:58:26 ' 427 new_text = text
' 428
' 429 for user in self.sorted_len_usernames:
' 430 if user == self.tg_username:
' 431 if me_nick:
' 432 username = me_nick
' 433 else:
' 434 continue
' 435 else:
' 436 username = self.irc.users[user].irc_nick
' 437
2023-06-15 E. 438 if received:
2023-07-07 E. 439 mention = mark + user
23:58:26 ' 440 mention_case = mark + username
' 441 else: # sent
' 442 mention = user + mark
' 443 mention_case = username + mark
' 444 replcmnt = repl_pref + username + repl_suff
' 445
' 446 # Start of the text
' 447 for ment in (mention, mention_case):
' 448 if new_text.startswith(ment):
' 449 new_text = new_text.replace(ment, replcmnt, 1)
' 450
' 451 # Next words (with space as separator)
' 452 mention = ' ' + mention
' 453 mention_case = ' ' + mention_case
' 454 replcmnt = ' ' + replcmnt
' 455 new_text = new_text.replace(mention, replcmnt).replace(mention_case, replcmnt)
' 456
' 457 return new_text
2023-06-15 E. 458
18:08:03 ' 459 if received:
' 460 mark = '@'
' 461 rargs['repl_pref'] = '~'
' 462 rargs['repl_suff'] = '~'
2023-07-07 E. 463 else: # sent
2023-06-15 E. 464 mark = ':'
18:08:03 ' 465 rargs['repl_pref'] = '@'
' 466 rargs['repl_suff'] = ''
' 467
' 468 if text.find(mark) != -1:
2023-07-07 E. 469 text_replaced = repl_mentioned(text, me_nick, received, mark, **rargs)
2023-05-20 E. 470 else:
21:39:03 ' 471 text_replaced = text
' 472 return text_replaced
' 473
' 474 def filters(self, text):
' 475 filtered = e.replace_mult(text, e.emo)
' 476 filtered = self.replace_mentions(filtered)
' 477 return filtered
' 478
2023-07-07 E. 479 def add_sorted_len_usernames(self, username):
23:58:26 ' 480 self.sorted_len_usernames.append(username)
' 481 self.sorted_len_usernames.sort(key=lambda k: len(k), reverse=True)
' 482
2023-04-15 E. 483 async def handle_telegram_edited(self, event):
23:13:07 ' 484 self.logger.debug('Handling Telegram Message Edited: %s', event)
' 485
' 486 id = event.message.id
2023-05-15 E. 487 mid = self.mid.num_to_id_offset(event.message.peer_id, id)
2023-04-15 E. 488 fmid = '[{}]'.format(mid)
2023-05-20 E. 489 message = self.filters(event.message.message)
2023-05-02 E. 490 message_rendered = await self.render_text(event.message, mid, upd_to_webpend=None)
2023-04-15 E. 491
2023-04-25 E. 492 edition_case, reaction = await self.edition_case(event.message)
20:34:42 ' 493 if edition_case == 'edition':
' 494 action = 'Edited'
' 495 user = self.get_irc_user_from_telegram(event.sender_id)
' 496 if id in self.cache:
2023-05-20 E. 497 t = self.filters(self.cache[id]['text'])
2023-04-25 E. 498 rt = self.cache[id]['rendered_text']
20:34:42 ' 499
' 500 ht, is_ht = get_highlighted(t, message)
' 501 else:
' 502 rt = fmid
' 503 is_ht = False
' 504
' 505 if is_ht:
' 506 edition_react = ht
' 507 text_old = fmid
' 508 else:
' 509 edition_react = message
' 510 text_old = rt
' 511 if user is None:
' 512 self.refwd_me = True
' 513
' 514 # Reactions
2023-04-15 E. 515 else:
2023-04-25 E. 516 action = 'React'
2023-04-26 E. 517 if len(message_rendered) > self.quote_len:
18:45:17 ' 518 text_old = '{}...'.format(message_rendered[:self.quote_len])
' 519 text_old = fix_braces(text_old)
2023-04-25 E. 520 else:
20:34:42 ' 521 text_old = message_rendered
' 522
' 523 if edition_case == 'react-add':
' 524 user = self.get_irc_user_from_telegram(reaction.peer_id.user_id)
' 525 emoji = reaction.reaction.emoticon
' 526 react_action = '+'
2023-04-29 E. 527 react_icon = e.emo[emoji] if emoji in e.emo else emoji
2023-04-25 E. 528 elif edition_case == 'react-del':
20:34:42 ' 529 user = self.get_irc_user_from_telegram(event.sender_id)
' 530 react_action = '-'
' 531 react_icon = ''
' 532 edition_react = '{}{}'.format(react_action, react_icon)
' 533
' 534 text = '|{} {}| {}'.format(action, text_old, edition_react)
' 535
2023-04-15 E. 536 chan = await self.relay_telegram_message(event, user, text)
23:13:07 ' 537
2023-04-25 E. 538 self.to_cache(id, mid, message, message_rendered, user, chan, event.message.media)
2023-04-15 E. 539
2023-04-10 E. 540 async def handle_telegram_deleted(self, event):
21:31:19 ' 541 self.logger.debug('Handling Telegram Message Deleted: %s', event)
' 542
' 543 for deleted_id in event.original_update.messages:
' 544 if deleted_id in self.cache:
' 545 recovered_text = self.cache[deleted_id]['rendered_text']
' 546 text = '|Deleted| {}'.format(recovered_text)
' 547 user = self.cache[deleted_id]['user']
' 548 chan = self.cache[deleted_id]['channel']
2023-05-06 E. 549 await self.relay_telegram_message(message=None, user=user, text=text, channel=chan)
2023-04-10 E. 550 else:
2023-05-15 E. 551 text = 'Message id {} deleted not in cache'.format(deleted_id)
2023-04-10 E. 552 await self.relay_telegram_private_message(self.irc.service_user, text)
21:31:19 ' 553
2022-02-08 E. 554 async def handle_raw(self, update):
2023-03-31 E. 555 self.logger.debug('Handling Telegram Raw Event: %s', update)
20:46:58 ' 556
2022-02-08 E. 557 if isinstance(update, tgty.UpdateWebPage) and isinstance(update.webpage, tgty.WebPage):
2023-05-02 E. 558 message = self.webpending.pop(update.webpage.id, None)
21:37:17 ' 559 if message:
' 560 await self.handle_telegram_message(event=None, message=message, upd_to_webpend=update.webpage)
' 561
2023-05-06 E. 562 async def handle_telegram_message(self, event, message=None, upd_to_webpend=None, history=False):
2023-05-02 E. 563 self.logger.debug('Handling Telegram Message: %s', event or message)
21:37:17 ' 564
2023-05-04 E. 565 msg = event.message if event else message
2023-05-02 E. 566
21:37:17 ' 567 user = self.get_irc_user_from_telegram(msg.sender_id)
2023-05-15 E. 568 mid = self.mid.num_to_id_offset(msg.peer_id, msg.id)
2023-10-15 E. 569 text = await self.render_text(msg, mid, upd_to_webpend, user)
2023-11-26 E. 570 text_send = self.set_history_timestamp(text, history, msg.date, msg.action)
2023-05-06 E. 571 chan = await self.relay_telegram_message(msg, user, text_send)
2023-05-02 E. 572
21:37:17 ' 573 self.to_cache(msg.id, mid, msg.message, text, user, chan, msg.media)
2023-04-15 E. 574
23:13:07 ' 575 self.refwd_me = False
' 576
2023-10-15 E. 577 async def render_text(self, message, mid, upd_to_webpend, user=None):
2022-02-08 E. 578 if upd_to_webpend:
2023-12-17 E. 579 text = await self.handle_webpage(upd_to_webpend, message, mid)
2023-05-02 E. 580 elif message.media:
2023-10-15 E. 581 text = await self.handle_telegram_media(message, user, mid)
2022-01-30 E. 582 else:
2023-05-02 E. 583 text = message.message
21:37:17 ' 584
2023-11-26 E. 585 if message.action:
2023-12-17 E. 586 final_text = await self.handle_telegram_action(message, mid)
2023-11-26 E. 587 return final_text
19:07:44 ' 588 elif message.is_reply:
2023-05-02 E. 589 refwd_text = await self.handle_telegram_reply(message)
21:37:17 ' 590 elif message.forward:
' 591 refwd_text = await self.handle_telegram_forward(message)
2023-03-28 E. 592 else:
21:32:36 ' 593 refwd_text = ''
' 594
2023-12-02 E. 595 target_mine = self.handle_target_mine(message.peer_id, user)
19:41:44 ' 596
' 597 final_text = '[{}] {}{}{}'.format(mid, target_mine, refwd_text, text)
2023-05-20 E. 598 final_text = self.filters(final_text)
2023-05-02 E. 599 return final_text
21:37:17 ' 600
2023-11-26 E. 601 def set_history_timestamp(self, text, history, date, action):
2023-05-06 E. 602 if history and self.hist_fmt:
23:31:34 ' 603 timestamp = format_timestamp(self.hist_fmt, self.timezone, date)
2023-11-26 E. 604 if action:
19:07:44 ' 605 res = '{} {}'.format(text, timestamp)
' 606 else:
' 607 res = '{} {}'.format(timestamp, text)
2023-05-06 E. 608 else:
23:31:34 ' 609 res = text
' 610 return res
' 611
2023-05-02 E. 612 async def relay_telegram_message(self, message, user, text, channel=None):
21:37:17 ' 613 private = (message and message.is_private) or (not message and not channel)
2023-11-26 E. 614 action = (message and message.action)
2023-04-08 E. 615 if private:
2023-11-26 E. 616 await self.relay_telegram_private_message(user, text, action)
2023-04-08 E. 617 chan = None
2020-11-21 E. 618 else:
2023-11-26 E. 619 chan = await self.relay_telegram_channel_message(message, user, text, channel, action)
2023-04-08 E. 620 return chan
2023-03-28 E. 621
2023-11-26 E. 622 async def relay_telegram_private_message(self, user, message, action=None):
2022-01-26 E. 623 self.logger.debug('Handling Telegram Private Message: %s, %s', user, message)
2022-01-24 E. 624
2023-11-26 E. 625 if action:
19:07:44 ' 626 await self.irc.send_action(user, None, message)
' 627 else:
' 628 await self.irc.send_msg(user, None, message)
' 629
' 630 async def relay_telegram_channel_message(self, message, user, text, channel, action):
2023-05-02 E. 631 self.logger.debug('Handling Telegram Channel Message: %s', message or text)
21:37:17 ' 632
' 633 if message:
' 634 entity = await message.get_chat()
' 635 chan = await self.get_irc_channel_from_telegram_id(message.chat_id, entity)
2023-04-08 E. 636 else:
23:07:35 ' 637 chan = channel
2023-11-26 E. 638
19:07:44 ' 639 if action:
' 640 await self.irc.send_action(user, chan, text)
' 641 else:
' 642 await self.irc.send_msg(user, chan, text)
' 643
2023-04-08 E. 644 return chan
2020-11-21 E. 645
01:12:30 ' 646 async def handle_telegram_chat_action(self, event):
' 647 self.logger.debug('Handling Telegram Chat Action: %s', event)
' 648
' 649 try:
' 650 tid = event.action_message.to_id.channel_id
' 651 except AttributeError:
' 652 tid = event.action_message.to_id.chat_id
' 653 finally:
' 654 irc_channel = await self.get_irc_channel_from_telegram_id(tid)
' 655 await self.get_telegram_channel_participants(tid)
' 656
' 657 try: # Join Chats
' 658 irc_nick = await self.get_irc_nick_from_telegram_id(event.action_message.action.users[0])
' 659 except (IndexError, AttributeError):
' 660 try: # Kick
' 661 irc_nick = await self.get_irc_nick_from_telegram_id(event.action_message.action.user_id)
' 662 except (IndexError, AttributeError): # Join Channels
' 663 irc_nick = await self.get_irc_nick_from_telegram_id(event.action_message.sender_id)
' 664
' 665 if event.user_added or event.user_joined:
2023-03-24 E. 666 await self.irc.join_irc_channel(irc_nick, irc_channel, full_join=False)
2020-11-21 E. 667 elif event.user_kicked or event.user_left:
01:12:30 ' 668 await self.irc.part_irc_channel(irc_nick, irc_channel)
' 669
' 670 async def join_all_telegram_channels(self):
' 671 async for dialog in self.telegram_client.iter_dialogs():
' 672 chat = dialog.entity
2021-02-01 E. 673 if not isinstance(chat, tgty.User):
2020-11-21 E. 674 channel = self.get_telegram_channel(chat)
01:12:30 ' 675 self.tid_to_iid[chat.id] = channel
' 676 self.irc.iid_to_tid[channel] = chat.id
2023-03-24 E. 677 await self.irc.join_irc_channel(self.irc.irc_nick, channel, full_join=True)
2020-11-21 E. 678
2023-12-17 E. 679 async def handle_telegram_action(self, message, mid):
2023-11-26 E. 680 if isinstance(message.action, tgty.MessageActionPinMessage):
19:07:44 ' 681 replied = await message.get_reply_message()
' 682 cid = self.mid.num_to_id_offset(replied.peer_id, replied.id)
' 683 action_text = 'has pinned message [{}]'.format(cid)
2023-11-26 E. 684 elif isinstance(message.action, tgty.MessageActionChatEditPhoto):
22:13:52 ' 685 _, media_type = self.scan_photo_attributes(message.action.photo)
2023-12-17 E. 686 photo_url = await self.download_telegram_media(message, mid)
2023-11-26 E. 687 action_text = 'has changed chat [{}] {}'.format(media_type, photo_url)
2023-11-26 E. 688 else:
19:07:44 ' 689 action_text = ''
' 690 return action_text
' 691
2023-05-02 E. 692 async def handle_telegram_reply(self, message):
2023-07-22 E. 693 space = ' '
2023-03-28 E. 694 trunc = ''
2023-05-02 E. 695 replied = await message.get_reply_message()
21:37:17 ' 696 replied_msg = replied.message
2023-07-22 E. 697 cid = self.mid.num_to_id_offset(replied.peer_id, replied.id)
2023-05-02 E. 698 if not replied_msg:
2023-07-22 E. 699 replied_msg = ''
18:32:19 ' 700 space = ''
2023-05-02 E. 701 elif len(replied_msg) > self.quote_len:
21:37:17 ' 702 replied_msg = replied_msg[:self.quote_len]
2023-03-28 E. 703 trunc = '...'
21:32:36 ' 704 replied_user = self.get_irc_user_from_telegram(replied.sender_id)
' 705 if replied_user is None:
' 706 replied_nick = '{}'
' 707 self.refwd_me = True
' 708 else:
' 709 replied_nick = replied_user.irc_nick
' 710
2023-07-22 E. 711 return '|Re {}: [{}]{}{}{}| '.format(replied_nick, cid, space, replied_msg, trunc)
2023-05-02 E. 712
21:37:17 ' 713 async def handle_telegram_forward(self, message):
2023-06-07 E. 714 space = space2 = ' '
22:26:21 ' 715 if not (forwarded_peer_name := await self.get_irc_name_from_telegram_forward(message.fwd_from, saved=False)):
' 716 space = ''
' 717 saved_peer_name = await self.get_irc_name_from_telegram_forward(message.fwd_from, saved=True)
' 718 if saved_peer_name and saved_peer_name != forwarded_peer_name:
' 719 secondary_name = saved_peer_name
2023-03-28 E. 720 else:
21:32:36 ' 721 # if it's from me I want to know who was the destination of a message (user)
2024-04-07 E. 722 if self.refwd_me and (saved_from_peer := message.fwd_from.saved_from_peer) is not None:
17:48:33 ' 723 secondary_name = self.get_irc_user_from_telegram(saved_from_peer.user_id).irc_nick
2023-03-28 E. 724 else:
2023-06-07 E. 725 secondary_name = ''
22:26:21 ' 726 space2 = ''
' 727
' 728 return '|Fwd{}{}{}{}| '.format(space, forwarded_peer_name, space2, secondary_name)
2023-03-28 E. 729
2023-10-15 E. 730 async def handle_telegram_media(self, message, user, mid):
2022-01-30 E. 731 caption = ' | {}'.format(message.message) if message.message else ''
00:29:08 ' 732 to_download = True
' 733 media_url_or_data = ''
2023-10-15 E. 734 size = 0
2023-11-18 E. 735 filename = None
23:43:04 ' 736
' 737 def scan_doc_attributes(document):
2023-12-14 E. 738 attrib_file = attrib_av = filename = None
2023-11-18 E. 739 size = document.size
23:43:04 ' 740 h_size = get_human_size(size)
' 741 for x in document.attributes:
2023-12-14 E. 742 if isinstance(x, tgty.DocumentAttributeVideo) or isinstance(x, tgty.DocumentAttributeAudio):
23:00:44 ' 743 attrib_av = x
2023-11-18 E. 744 if isinstance(x, tgty.DocumentAttributeFilename):
23:43:04 ' 745 attrib_file = x
' 746 filename = attrib_file.file_name if attrib_file else None
' 747
2023-12-14 E. 748 return size, h_size, attrib_av, filename
2022-01-30 E. 749
2022-02-08 E. 750 if isinstance(message.media, tgty.MessageMediaWebPage):
2022-01-30 E. 751 to_download = False
2022-02-08 E. 752 if isinstance(message.media.webpage, tgty.WebPage):
01:04:55 ' 753 # web
2023-12-17 E. 754 return await self.handle_webpage(message.media.webpage, message, mid)
2022-02-08 E. 755 elif isinstance(message.media.webpage, tgty.WebPagePending):
01:04:55 ' 756 media_type = 'webpending'
' 757 media_url_or_data = message.message
' 758 caption = ''
2023-05-02 E. 759 self.webpending[message.media.webpage.id] = message
2022-01-30 E. 760 else:
2022-02-08 E. 761 media_type = 'webunknown'
01:04:55 ' 762 media_url_or_data = message.message
2022-01-30 E. 763 caption = ''
2022-01-30 E. 764 elif message.photo:
2023-11-26 E. 765 size, media_type = self.scan_photo_attributes(message.media.photo)
2023-12-14 E. 766 elif message.audio:
23:00:44 ' 767 size, h_size, attrib_audio, filename = scan_doc_attributes(message.media.document)
' 768 dur = get_human_duration(attrib_audio.duration) if attrib_audio else ''
' 769 per = attrib_audio.performer or ''
' 770 tit = attrib_audio.title or ''
' 771 theme = ',{}/{}'.format(per, tit) if per or tit else ''
' 772 media_type = 'audio:{},{}{}'.format(h_size, dur, theme)
' 773 elif message.voice:
' 774 size, _, attrib_audio, filename = scan_doc_attributes(message.media.document)
' 775 dur = get_human_duration(attrib_audio.duration) if attrib_audio else ''
' 776 media_type = 'rec:{}'.format(dur)
2022-02-09 E. 777 elif message.video:
2023-11-18 E. 778 size, h_size, attrib_video, filename = scan_doc_attributes(message.media.document)
23:43:04 ' 779 dur = get_human_duration(attrib_video.duration) if attrib_video else ''
2023-10-15 E. 780 media_type = 'video:{},{}'.format(h_size, dur)
2022-01-30 E. 781 elif message.video_note: media_type = 'videorec'
00:29:08 ' 782 elif message.gif: media_type = 'anim'
' 783 elif message.sticker: media_type = 'sticker'
2022-02-09 E. 784 elif message.document:
2023-11-18 E. 785 size, h_size, _, filename = scan_doc_attributes(message.media.document)
2023-10-15 E. 786 media_type = 'file:{}'.format(h_size)
2022-01-30 E. 787 elif message.contact:
00:29:08 ' 788 media_type = 'contact'
' 789 caption = ''
' 790 to_download = False
2023-06-01 E. 791 if message.media.first_name:
17:55:14 ' 792 media_url_or_data += message.media.first_name + ' '
' 793 if message.media.last_name:
' 794 media_url_or_data += message.media.last_name + ' '
' 795 if message.media.phone_number:
' 796 media_url_or_data += message.media.phone_number
2022-01-30 E. 797
00:29:08 ' 798 elif message.game:
' 799 media_type = 'game'
' 800 caption = ''
' 801 to_download = False
' 802 if message.media.game.title:
' 803 media_url_or_data = message.media.game.title
' 804
' 805 elif message.geo:
' 806 media_type = 'geo'
' 807 caption = ''
' 808 to_download = False
2023-07-20 E. 809 if self.geo_url:
23:12:18 ' 810 geo_url = ' | ' + self.geo_url
' 811 else:
' 812 geo_url = ''
' 813 lat_long_template = 'lat: {lat}, long: {long}' + geo_url
' 814 media_url_or_data = lat_long_template.format(lat=message.media.geo.lat, long=message.media.geo.long)
2022-01-30 E. 815
00:29:08 ' 816 elif message.invoice:
' 817 media_type = 'invoice'
' 818 caption = ''
' 819 to_download = False
' 820 media_url_or_data = ''
' 821
' 822 elif message.poll:
' 823 media_type = 'poll'
' 824 caption = ''
' 825 to_download = False
2023-10-10 E. 826 media_url_or_data = self.handle_poll(message.media.poll)
2022-01-30 E. 827
00:29:08 ' 828 elif message.venue:
' 829 media_type = 'venue'
' 830 caption = ''
' 831 to_download = False
' 832 media_url_or_data = ''
2022-02-08 E. 833 else:
01:04:55 ' 834 media_type = 'unknown'
' 835 caption = ''
' 836 to_download = False
' 837 media_url_or_data = message.message
2022-01-30 E. 838
00:29:08 ' 839 if to_download:
2023-11-18 E. 840 relay_attr = (message, user, mid, media_type)
2023-12-17 E. 841 media_url_or_data = await self.download_telegram_media(message, mid, filename, size, relay_attr)
2022-01-30 E. 842
2022-02-08 E. 843 return self.format_media(media_type, media_url_or_data, caption)
01:04:55 ' 844
2023-10-10 E. 845 def handle_poll(self, poll):
22:35:28 ' 846 text = poll.question
' 847 for ans in poll.answers:
' 848 text += '\n* ' + ans.text
' 849 return text
' 850
2023-12-02 E. 851 def handle_target_mine(self, target, user):
19:41:44 ' 852 # Add the target of messages sent by self user (me)
' 853 # received in other clients
' 854 target_id, target_type = self.get_peer_id_and_type(target)
' 855 if user is None and target_type == 'user' and target_id != self.id:
' 856 # self user^
' 857 # as sender
' 858 irc_id = self.get_irc_name_from_telegram_id(target_id)
' 859 target_mine = '[T: {}] '.format(irc_id)
' 860 else:
' 861 target_mine = ''
' 862 return target_mine
' 863
2023-12-17 E. 864 async def handle_webpage(self, webpage, message, mid):
2022-02-08 E. 865 media_type = 'web'
2023-12-17 E. 866 logo = await self.download_telegram_media(message, mid)
2022-02-19 E. 867 if is_url_equiv(webpage.url, webpage.display_url):
01:10:00 ' 868 url_data = webpage.url
2022-02-08 E. 869 else:
2022-02-19 E. 870 url_data = '{} | {}'.format(webpage.url, webpage.display_url)
2022-02-08 E. 871 if message:
01:04:55 ' 872 # sometimes the 1st line of message contains the title, don't repeat it
' 873 message_line = message.message.splitlines()[0]
' 874 if message_line != webpage.title:
' 875 title = webpage.title
' 876 else:
' 877 title = ''
2022-02-19 E. 878 # extract the URL in the message, don't repeat it
01:10:00 ' 879 message_url = extract_url(message.message)
' 880 if is_url_equiv(message_url, webpage.url):
' 881 if is_url_equiv(message_url, webpage.display_url):
' 882 media_url_or_data = message.message
' 883 else:
' 884 media_url_or_data = '{} | {}'.format(message.message, webpage.display_url)
' 885 else:
' 886 media_url_or_data = '{} | {}'.format(message.message, url_data)
2022-02-08 E. 887 else:
01:04:55 ' 888 title = webpage.title
2022-02-19 E. 889 media_url_or_data = url_data
2022-02-08 E. 890
01:04:55 ' 891 if title and logo:
' 892 caption = ' | {} | {}'.format(title, logo)
' 893 elif title:
' 894 caption = ' | {}'.format(title)
' 895 elif logo:
' 896 caption = ' | {}'.format(logo)
' 897 else:
' 898 caption = ''
' 899
' 900 return self.format_media(media_type, media_url_or_data, caption)
' 901
' 902 def format_media(self, media_type, media_url_or_data, caption):
2022-01-30 E. 903 return '[{}] {}{}'.format(media_type, media_url_or_data, caption)
00:29:08 ' 904
2023-11-26 E. 905 def scan_photo_attributes(self, photo):
22:13:52 ' 906 size = 0
' 907 sizes = photo.sizes
' 908 ph_size = sizes[-1]
' 909 if isinstance(ph_size, tgty.PhotoSizeProgressive):
' 910 size = ph_size.sizes[-1]
' 911 else:
' 912 for x in sizes:
' 913 if isinstance(x, tgty.PhotoSize):
' 914 if x.size > size:
' 915 size = x.size
' 916 ph_size = x
' 917 if hasattr(ph_size, 'w') and hasattr(ph_size, 'h'):
' 918 media_type = 'photo:{}x{}'.format(ph_size.w, ph_size.h)
' 919 else:
' 920 media_type = 'photo'
' 921
' 922 return size, media_type
' 923
2023-12-17 E. 924 async def download_telegram_media(self, message, mid, filename=None, size=0, relay_attr=None):
2023-11-18 E. 925 if not self.download:
23:43:04 ' 926 return ''
' 927 if filename:
2023-12-17 E. 928 idd_file = add_filename(filename, mid)
01:49:18 ' 929 new_file = sanitize_filename(idd_file)
2023-11-18 E. 930 new_path = os.path.join(self.telegram_media_dir, new_file)
23:43:04 ' 931 if os.path.exists(new_path):
' 932 local_path = new_path
' 933 else:
' 934 await self.notice_downloading(size, relay_attr)
' 935 local_path = await message.download_media(new_path)
' 936 if not local_path: return ''
' 937 else:
' 938 await self.notice_downloading(size, relay_attr)
2023-10-15 E. 939 local_path = await message.download_media(self.telegram_media_dir)
2023-11-18 E. 940 if not local_path: return ''
2022-01-30 E. 941 filetype = os.path.splitext(local_path)[1]
2023-12-17 E. 942 gen_file = str(self.media_cn) + filetype
01:49:18 ' 943 idd_file = add_filename(gen_file, mid)
' 944 new_file = sanitize_filename(idd_file)
2022-01-30 E. 945 self.media_cn += 1
2023-11-18 E. 946 new_path = os.path.join(self.telegram_media_dir, new_file)
23:43:04 ' 947
2022-01-30 E. 948 if local_path != new_path:
00:29:08 ' 949 os.replace(local_path, new_path)
' 950 if self.media_url[-1:] != '/':
' 951 self.media_url += '/'
' 952 return self.media_url + new_file
2022-01-26 E. 953
2023-11-18 E. 954 async def notice_downloading(self, size, relay_attr):
23:43:04 ' 955 if relay_attr and size > self.notice_size:
' 956 message, user, mid, media_type = relay_attr
' 957 await self.relay_telegram_message(message, user, '[{}] [{}] [Downloading]'.format(mid, media_type))
' 958
2022-01-26 E. 959 class mesg_id:
21:30:58 ' 960 def __init__(self, alpha):
' 961 self.alpha = alpha
' 962 self.base = len(alpha)
' 963 self.alphaval = { i:v for v, i in enumerate(alpha) }
2023-05-15 E. 964 self.mesg_base = {}
2022-01-26 E. 965
21:30:58 ' 966 def num_to_id(self, num, neg=''):
' 967 if num < 0: return self.num_to_id(-num, '-')
' 968 (high, low) = divmod(num, self.base)
' 969 if high >= self.base:
' 970 aux = self.num_to_id(high)
' 971 return neg + aux + self.alpha[low]
' 972 else:
' 973 return neg + self.alpha[high] + self.alpha[low]
' 974
2023-05-15 E. 975 def num_to_id_offset(self, peer, num):
19:27:05 ' 976 peer_id = self.get_peer_id(peer)
' 977 if peer_id not in self.mesg_base:
' 978 self.mesg_base[peer_id] = num
' 979 return self.num_to_id(num - self.mesg_base[peer_id])
2023-04-10 E. 980
2022-01-26 E. 981 def id_to_num(self, id, n=1):
21:30:58 ' 982 if id:
' 983 if id[0] == '-': return self.id_to_num(id[1:], -1)
' 984 aux = self.alphaval[id[-1:]] * n
' 985 sum = self.id_to_num(id[:-1], n * self.base)
' 986 return sum + aux
' 987 else:
' 988 return 0
2023-05-13 E. 989
2023-05-15 E. 990 def id_to_num_offset(self, peer, mid):
19:27:05 ' 991 peer_id = self.get_peer_id(peer)
' 992 if peer_id in self.mesg_base:
2023-05-13 E. 993 id_rel = self.id_to_num(mid)
2023-05-15 E. 994 id = id_rel + self.mesg_base[peer_id]
2023-05-13 E. 995 else:
22:39:42 ' 996 id = None
2023-05-15 E. 997 return id
19:27:05 ' 998
' 999 def get_peer_id(self, peer):
' 1000 if isinstance(peer, tgty.PeerChannel):
' 1001 id = peer.channel_id
' 1002 elif isinstance(peer, tgty.PeerChat):
' 1003 id = peer.chat_id
' 1004 elif isinstance(peer, tgty.PeerUser):
' 1005 id = peer.user_id
' 1006 else:
' 1007 id = peer
2023-05-13 E. 1008 return id