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