patch 3f2611ef2ec2a73f0327df45855e40f04ebb5955 Author: E. Bosch Date: Tue Jul 7 23:15:14 CEST 2026 * Merge pull request #11 on github from Mirochill/fix-9-invalid-escape-warnings Fix invalid escape warnings patch 7827ddfc286acd03ba80f6dfef6efed92fc0457a Author: E. Bosch Date: Sun Jun 21 23:41:03 CEST 2026 * Update year in copyright notices patch 6493c04f9d8bdb7b1d2c037fdd66c337a7a91af5 Author: E. Bosch Date: Sun May 31 00:26:34 CEST 2026 * utils: Modify sanitize_filename(): convert invalid chars to hex representation, this makes the filenames deterministic for the same session, and helps to not download a file more than once patch dd18dbebc3877faa7fe1c7f1257fb3a4048aab32 Author: E. Bosch Date: Sat May 30 22:25:32 CEST 2026 * utils: In add_filename() don't put a final dot if there is no extension in the filename patch feebc9eac596c484be6e5f67934196e64d52beeb Author: E. Bosch Date: Sat May 30 21:33:57 CEST 2026 * telegram: Refactor download media routine optimized to download files only once utils: Add session tokens for unnamed files patch 4009bc07c6261c0ea2cb1a4112f8aaf266cbd65d Author: E. Bosch Date: Sat Jul 26 01:56:12 CEST 2025 * emoji2emoticon: Add emoji "rolling on the floor laughing" to convert to ASCII diff -rN -u old-irgramd/LICENSE new-irgramd/LICENSE --- old-irgramd/LICENSE 2026-07-08 08:10:46.164363440 +0200 +++ new-irgramd/LICENSE 2026-07-08 08:10:46.244363356 +0200 @@ -1,7 +1,7 @@ MIT License Copyright (c) 2019 Peter Bui -Copyright (c) 2020-2024 E. Bosch +Copyright (c) 2020-2026 E. Bosch Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -rN -u old-irgramd/README.md new-irgramd/README.md --- old-irgramd/README.md 2026-07-08 08:10:46.164363440 +0200 +++ new-irgramd/README.md 2026-07-08 08:10:46.244363356 +0200 @@ -125,7 +125,7 @@ ## License Copyright (c) 2019 Peter Bui -Copyright (c) 2020-2024 E. Bosch +Copyright (c) 2020-2026 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. diff -rN -u old-irgramd/emoji2emoticon.py new-irgramd/emoji2emoticon.py --- old-irgramd/emoji2emoticon.py 2026-07-08 08:10:46.212363389 +0200 +++ new-irgramd/emoji2emoticon.py 2026-07-08 08:10:46.244363356 +0200 @@ -1,7 +1,7 @@ # irgramd: IRC-Telegram gateway # emoji2emoticon.py: UTF-8 Emoji to ASCII emoticon replacement # -# (C) Copyright 2019,2023 E. Bosch +# (C) Copyright 2019,2023,2025 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. @@ -14,7 +14,7 @@ '\U0001f44d': '"+1"', '\U0001f44e': '"-1"', '\U0001f44f': '"m_m"', - '\U0001f525': '"\^^^/"', + '\U0001f525': r'"\^^^/"', '\U0001f600': '":D"', '\U0001f601': '"xD"', '\U0001f602': '"x_D"', @@ -85,6 +85,7 @@ '\U0001f643': '"(:"', '\U0001f644': '"o o,"', '\U0001f914': '":-L"', + '\U0001f923': '"X__D"', '\U0001f92b': '":-o-m"', '\U0001f970': '":)e>"', } diff -rN -u old-irgramd/exclam.py new-irgramd/exclam.py --- old-irgramd/exclam.py 2026-07-08 08:10:46.212363389 +0200 +++ new-irgramd/exclam.py 2026-07-08 08:10:46.248363352 +0200 @@ -1,7 +1,7 @@ # irgramd: IRC-Telegram gateway # exclam.py: IRC exclamation command handlers # -# Copyright (c) 2023, 2024 E. Bosch +# Copyright (c) 2023-2025 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. diff -rN -u old-irgramd/include.py new-irgramd/include.py --- old-irgramd/include.py 2026-07-08 08:10:46.220363381 +0200 +++ new-irgramd/include.py 2026-07-08 08:10:46.252363347 +0200 @@ -1,7 +1,7 @@ # irgramd: IRC-Telegram gateway # include.py: Constants and other definitions to be included in other files # -# Copyright (c) 2020-2022 E. Bosch +# Copyright (c) 2020-2024 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. diff -rN -u old-irgramd/irc.py new-irgramd/irc.py --- old-irgramd/irc.py 2026-07-08 08:10:46.220363381 +0200 +++ new-irgramd/irc.py 2026-07-08 08:10:46.252363347 +0200 @@ -2,7 +2,7 @@ # irc.py: IRC server side implementation # # Copyright (c) 2019 Peter Bui -# Copyright (c) 2020-2023 E. Bosch +# Copyright (c) 2020-2024 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. @@ -28,7 +28,7 @@ SRV = None ALL_PARAMS = 16 -VALID_IRC_NICK_FIRST_CHARS = string.ascii_letters + '[]\`_^{|}' +VALID_IRC_NICK_FIRST_CHARS = string.ascii_letters + r'[]\`_^{|}' VALID_IRC_NICK_CHARS = VALID_IRC_NICK_FIRST_CHARS + string.digits + '-' # IRC Regular Expressions diff -rN -u old-irgramd/service.py new-irgramd/service.py --- old-irgramd/service.py 2026-07-08 08:10:46.228363372 +0200 +++ new-irgramd/service.py 2026-07-08 08:10:46.256363343 +0200 @@ -1,7 +1,7 @@ # irgramd: IRC-Telegram gateway # service.py: IRC service/control command handlers # -# Copyright (c) 2022,2023 E. Bosch +# Copyright (c) 2022-2024 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. diff -rN -u old-irgramd/telegram.py new-irgramd/telegram.py --- old-irgramd/telegram.py 2026-07-08 08:10:46.228363372 +0200 +++ new-irgramd/telegram.py 2026-07-08 08:10:46.264363335 +0200 @@ -2,7 +2,7 @@ # telegram.py: Interface to Telethon Telegram library # # Copyright (c) 2019 Peter Bui -# Copyright (c) 2020-2024 E. Bosch +# Copyright (c) 2020-2026 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. @@ -23,7 +23,7 @@ from include import CHAN_MAX_LENGTH, NICK_MAX_LENGTH from irc import IRCUser from utils import sanitize_filename, add_filename, is_url_equiv, extract_url, get_human_size, get_human_duration -from utils import get_highlighted, fix_braces, format_timestamp, pretty, current_date +from utils import get_highlighted, fix_braces, format_timestamp, pretty, current_date, token import emoji2emoticon as e # Test IP table @@ -44,6 +44,8 @@ self.notice_size = settings['download_notice'] * 1048576 self.media_dir = settings['media_dir'] self.media_url = settings['media_url'] + if self.media_url[-1:] != '/': + self.media_url += '/' self.upload_dir = settings['upload_dir'] self.api_id = settings['api_id'] self.api_hash = settings['api_hash'] @@ -59,7 +61,8 @@ self.geo_url = settings['geo_url'] if not settings['emoji_ascii']: e.emo = {} - self.media_cn = 0 + self.token = token('+0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz') + self.filename_token = self.token.gen_token(5) self.irc = irc self.authorized = False self.id = None @@ -1028,30 +1031,25 @@ if not self.download: return '' if filename: - idd_file = add_filename(filename, mid) - new_file = sanitize_filename(idd_file) - new_path = os.path.join(self.telegram_media_dir, new_file) - if os.path.exists(new_path): - local_path = new_path + aux_file = filename + else: + if hasattr(message, 'file') and message.file is not None: + aux_file = self.filename_token + message.file.ext else: - await self.notice_downloading(size, relay_attr) - local_path = await message.download_media(new_path) - if not local_path: return '' + aux_file = self.filename_token + + idd_file = add_filename(aux_file, mid) + new_file = sanitize_filename(idd_file) + new_path = os.path.join(self.telegram_media_dir, new_file) + if os.path.exists(new_path) and (size == 0 or size == os.path.getsize(new_path)): + local_path = new_path else: await self.notice_downloading(size, relay_attr) - local_path = await message.download_media(self.telegram_media_dir) + local_path = await message.download_media(new_path) if not local_path: return '' - filetype = os.path.splitext(local_path)[1] - gen_file = str(self.media_cn) + filetype - idd_file = add_filename(gen_file, mid) - new_file = sanitize_filename(idd_file) - self.media_cn += 1 - new_path = os.path.join(self.telegram_media_dir, new_file) if local_path != new_path: os.replace(local_path, new_path) - if self.media_url[-1:] != '/': - self.media_url += '/' return self.media_url + new_file async def notice_downloading(self, size, relay_attr): diff -rN -u old-irgramd/utils.py new-irgramd/utils.py --- old-irgramd/utils.py 2026-07-08 08:10:46.236363364 +0200 +++ new-irgramd/utils.py 2026-07-08 08:10:46.264363335 +0200 @@ -2,7 +2,7 @@ # utils.py: Helper functions # # Copyright (c) 2019 Peter Bui -# Copyright (c) 2020-2024 E. Bosch +# Copyright (c) 2020-2026 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. @@ -14,10 +14,11 @@ import zoneinfo import difflib import logging +import random # Constants -FILENAME_INVALID_CHARS = re.compile('[/{}<>()"\'\\|&#%?]') +FILENAME_INVALID_CHARS = re.compile('[\0-\x1F/{}<>"\'\\|*&#%?\x7F]') SIMPLE_URL = re.compile('http(|s)://[^ ]+') from include import MAX_LINE @@ -86,22 +87,23 @@ return messages_limited def sanitize_filename(fn): - cn = str(sanitize_filename.cn) - new_fn, ns = FILENAME_INVALID_CHARS.subn(cn, fn) - if ns: - sanitize_filename.cn += 1 - return new_fn.strip('-').replace(' ','_') -sanitize_filename.cn = 0 + def hexize(m): + return '-{:x}-'.format(ord(m.group(0))) + + new_fn = FILENAME_INVALID_CHARS.sub(hexize, fn) + return new_fn.lstrip('-').replace(' ','_') def add_filename(filename, add): if add: aux = filename.rsplit('.', 1) name = aux[0] + last_dot = '.' try: ext = aux[1] except: ext = '' - return '{}-{}.{}'.format(name, add, ext) + last_dot = '' + return '{}-{}{}{}'.format(name, add, last_dot, ext) else: return filename @@ -240,3 +242,15 @@ def pretty(object): return object.stringify() if LOGL.debug and object else object + +class token: + def __init__(self, alpha): + self.alpha = alpha + self.long_alpha = len(alpha) + + def gen_token(self, long_token): + if long_token == 1: + return self.alpha[random.randrange(self.long_alpha)] + else: + aux = self.gen_token(long_token - 1) + return aux + self.alpha[random.randrange(self.long_alpha)]