Skip to content

Commit

Permalink
feat: support for custom Telegram API endpoints and local Tglib Bot A…
Browse files Browse the repository at this point in the history
…PI client mode (fixes #116)
  • Loading branch information
blueset committed Jan 17, 2022
1 parent 37f93da commit cdda04a
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 23 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Unreleased

Added
-----
- Support for custom Telegram API endpoints and local Tglib Bot API client mode.
(`#116`_)

Changed
-------
Expand Down Expand Up @@ -198,3 +200,4 @@ First release.
.. _#103: https://etm.1a23.studio/issues/103
.. _#104: https://etm.1a23.studio/issues/104
.. _#110: https://etm.1a23.studio/pull/110
.. _#116: https://etm.1a23.studio/issues/116
15 changes: 15 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,21 @@ e.g.:
- ``text``: Use text like “Sent a picture/video/file”.
- ``disabled``: Use empty placeholders.

- ``api_base_url`` *(str)* [Default: ``null``]

Base URL of the Telegram Bot API.
Defaulted to ``https://api.telegram.org/bot``.

- ``api_base_file_url`` *(str)* [Default: ``null``]

Base file URL of the Telegram Bot API.
Defaulted to ``https://api.telegram.org/file/bot``.

- ``local_tdlib_api`` *(bool)* [Default: ``false``]

Enable this option if the bot API is running in ``--local`` mode and
is using the same file system with ETM.

Network configuration: timeout tweaks
-------------------------------------

Expand Down
8 changes: 4 additions & 4 deletions efb_telegram_master/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ def __init__(self, instance_id: InstanceID = None):
"https://pillow.readthedocs.io/"))

# Suppress debug logs from dependencies
logging.getLogger('requests').setLevel(logging.CRITICAL)
logging.getLogger('urllib3').setLevel(logging.CRITICAL)
logging.getLogger('telegram.bot').setLevel(logging.CRITICAL)
logging.getLogger('telegram.vendor.ptb_urllib3.urllib3.connectionpool').setLevel(logging.CRITICAL)
# logging.getLogger('requests').setLevel(logging.CRITICAL)
# logging.getLogger('urllib3').setLevel(logging.CRITICAL)
# logging.getLogger('telegram.bot').setLevel(logging.CRITICAL)
# logging.getLogger('telegram.vendor.ptb_urllib3.urllib3.connectionpool').setLevel(logging.CRITICAL)

# Set up logger
self.logger: logging.Logger = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion efb_telegram_master/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.2.5.dev1"
__version__ = "2.2.5.dev2"
2 changes: 2 additions & 0 deletions efb_telegram_master/bot_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ def __init__(self, channel: 'TelegramChannel'):

self.logger.debug("Setting up Telegram bot updater...")
self.updater: Updater = Updater(config['token'],
base_url=channel.flag('base_url'),
base_file_url=channel.flag('base_file_url'),
request_kwargs=req_kwargs,
use_context=True)

Expand Down
5 changes: 3 additions & 2 deletions efb_telegram_master/master_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ def _send_cached_chat_warning(self, update: Update,

def _check_file_download(self, file_obj: Any):
"""
Check if the file is available for download..
Check if the file is available for download.
Args:
file_obj (telegram.File): PTB file object
Expand All @@ -483,7 +483,8 @@ def _check_file_download(self, file_obj: Any):
EFBMessageError: When file exceeds the maximum download size.
"""
size = getattr(file_obj, "file_size", None)
if size and size > MAX_FILESIZE_DOWNLOAD:
if size and not self.channel.flag("local_tdlib_api")\
and size > MAX_FILESIZE_DOWNLOAD:
size_str = humanize.naturalsize(size)
max_size_str = humanize.naturalsize(MAX_FILESIZE_DOWNLOAD)
raise EFBMessageError(
Expand Down
51 changes: 35 additions & 16 deletions efb_telegram_master/slave_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import tempfile
import traceback
import urllib.parse
from typing import Tuple, Optional, TYPE_CHECKING, List, IO
from pathlib import Path
from typing import Tuple, Optional, TYPE_CHECKING, List, IO, Union

import humanize
import pydub
Expand Down Expand Up @@ -451,10 +452,11 @@ def slave_message_image(self, msg: Message, tg_dest: TelegramChatID, msg_templat
try:
if edit_media:
media: InputMedia
file = self.process_file_obj(msg.file, msg.path)
if send_as_file:
media = InputMediaDocument(msg.file)
media = InputMediaDocument(file)
else:
media = InputMediaPhoto(msg.file)
media = InputMediaPhoto(file)
self.bot.edit_message_media(chat_id=old_msg_id[0], message_id=old_msg_id[1], media=media)
return self.bot.edit_message_caption(chat_id=old_msg_id[0], message_id=old_msg_id[1],
reply_markup=reply_markup,
Expand All @@ -466,22 +468,25 @@ def slave_message_image(self, msg: Message, tg_dest: TelegramChatID, msg_templat
msg.file.seek(0)

if send_as_file:
return self.bot.send_document(tg_dest, msg.file, prefix=msg_template, suffix=reactions,
file = self.process_file_obj(msg.file, msg.path)
return self.bot.send_document(tg_dest, file, prefix=msg_template, suffix=reactions,
caption=text, parse_mode="HTML", filename=msg.filename,
reply_to_message_id=target_msg_id,
reply_markup=reply_markup,
disable_notification=silent)
else:
try:
return self.bot.send_photo(tg_dest, msg.file, prefix=msg_template, suffix=reactions,
file = self.process_file_obj(msg.file, msg.path)
return self.bot.send_photo(tg_dest, file, prefix=msg_template, suffix=reactions,
caption=text, parse_mode="HTML",
reply_to_message_id=target_msg_id,
reply_markup=reply_markup,
disable_notification=silent)
except telegram.error.BadRequest as e:
self.logger.error('[%s] Failed to send it as image, sending as document. Reason: %s',
msg.uid, e)
return self.bot.send_document(tg_dest, msg.file, prefix=msg_template, suffix=reactions,
file = self.process_file_obj(msg.file, msg.path)
return self.bot.send_document(tg_dest, file, prefix=msg_template, suffix=reactions,
caption=text, parse_mode="HTML", filename=msg.filename,
reply_to_message_id=target_msg_id,
reply_markup=reply_markup,
Expand Down Expand Up @@ -525,14 +530,16 @@ def slave_message_animation(self, msg: Message, tg_dest: TelegramChatID, msg_tem
if old_msg_id:
if edit_media:
assert msg.file
self.bot.edit_message_media(chat_id=old_msg_id[0], message_id=old_msg_id[1], media=InputMediaAnimation(msg.file))
file = self.process_file_obj(msg.file, msg.path)
self.bot.edit_message_media(chat_id=old_msg_id[0], message_id=old_msg_id[1], media=InputMediaAnimation(file))
return self.bot.edit_message_caption(chat_id=old_msg_id[0], message_id=old_msg_id[1],
prefix=msg_template, suffix=reactions,
reply_markup=reply_markup,
caption=text, parse_mode="HTML")
else:
assert msg.file
return self.bot.send_animation(tg_dest, InputFile(msg.file, filename=msg.filename),
file = self.process_file_obj(msg.file, msg.path)
return self.bot.send_animation(tg_dest, InputFile(file, filename=msg.filename),
prefix=msg_template, suffix=reactions,
caption=text, parse_mode="HTML",
reply_to_message_id=target_msg_id,
Expand Down Expand Up @@ -592,11 +599,13 @@ def slave_message_sticker(self, msg: Message, tg_dest: TelegramChatID, msg_templ
webp_img = tempfile.NamedTemporaryFile(suffix='.webp')
pic_img.convert("RGBA").save(webp_img, 'webp')
webp_img.seek(0)
return self.bot.send_sticker(tg_dest, webp_img, reply_markup=sticker_reply_markup,
file = self.process_file_obj(webp_img, webp_img.name)
return self.bot.send_sticker(tg_dest, file, reply_markup=sticker_reply_markup,
reply_to_message_id=target_msg_id,
disable_notification=silent)
except IOError:
return self.bot.send_document(tg_dest, msg.file, prefix=msg_template, suffix=reactions,
file = self.process_file_obj(msg.file, msg.path)
return self.bot.send_document(tg_dest, file, prefix=msg_template, suffix=reactions,
caption=msg.text, filename=msg.filename,
reply_to_message_id=target_msg_id,
reply_markup=reply_markup,
Expand Down Expand Up @@ -677,13 +686,15 @@ def slave_message_file(self, msg: Message, tg_dest: TelegramChatID, msg_template
if old_msg_id:
if edit_media:
assert msg.file is not None
self.bot.edit_message_media(chat_id=old_msg_id[0], message_id=old_msg_id[1], media=InputMediaDocument(msg.file))
file = self.process_file_obj(msg.file, msg.path)
self.bot.edit_message_media(chat_id=old_msg_id[0], message_id=old_msg_id[1], media=InputMediaDocument(file))
return self.bot.edit_message_caption(chat_id=old_msg_id[0], message_id=old_msg_id[1], reply_markup=reply_markup,
prefix=msg_template, suffix=reactions, caption=text, parse_mode="HTML")
assert msg.file is not None
self.logger.debug("[%s] Uploading file %s (%s) as %s", msg.uid,
msg.file.name, msg.mime, file_name)
return self.bot.send_document(tg_dest, msg.file,
file = self.process_file_obj(msg.file, msg.path)
return self.bot.send_document(tg_dest, file,
prefix=msg_template, suffix=reactions,
caption=text, parse_mode="HTML", filename=file_name,
reply_to_message_id=target_msg_id,
Expand Down Expand Up @@ -734,7 +745,8 @@ def slave_message_voice(self, msg: Message, tg_dest: TelegramChatID, msg_templat
with tempfile.NamedTemporaryFile() as f:
pydub.AudioSegment.from_file(msg.file).export(f, format="ogg", codec="libopus",
parameters=['-vbr', 'on'])
tg_msg = self.bot.send_voice(tg_dest, f, prefix=msg_template, suffix=reactions,
file = self.process_file_obj(f, f.name)
tg_msg = self.bot.send_voice(tg_dest, file, prefix=msg_template, suffix=reactions,
caption=text, parse_mode="HTML",
reply_to_message_id=target_msg_id, reply_markup=reply_markup,
disable_notification=silent)
Expand Down Expand Up @@ -809,11 +821,13 @@ def slave_message_video(self, msg: Message, tg_dest: TelegramChatID, msg_templat
if old_msg_id:
if edit_media:
assert msg.file is not None
self.bot.edit_message_media(chat_id=old_msg_id[0], message_id=old_msg_id[1], media=InputMediaVideo(msg.file))
file = self.process_file_obj(msg.file, msg.path)
self.bot.edit_message_media(chat_id=old_msg_id[0], message_id=old_msg_id[1], media=InputMediaVideo(file))
return self.bot.edit_message_caption(chat_id=old_msg_id[0], message_id=old_msg_id[1], reply_markup=reply_markup,
prefix=msg_template, suffix=reactions, caption=text, parse_mode="HTML")
assert msg.file is not None
return self.bot.send_video(tg_dest, msg.file, prefix=msg_template, suffix=reactions,
file = self.process_file_obj(msg.file, msg.path)
return self.bot.send_video(tg_dest, file, prefix=msg_template, suffix=reactions,
caption=text, parse_mode="HTML",
reply_to_message_id=target_msg_id,
reply_markup=reply_markup,
Expand Down Expand Up @@ -986,10 +1000,15 @@ def check_file_size(self, file: Optional[IO[bytes]]) -> Optional[str]:
file.seek(0, 2)
file_size = file.tell()
file.seek(0)
if file_size > telegram.constants.MAX_FILESIZE_UPLOAD:
if not self.channel.flag("local_tdlib_api") and file_size > telegram.constants.MAX_FILESIZE_UPLOAD:
size_str = humanize.naturalsize(file_size)
max_size_str = humanize.naturalsize(telegram.constants.MAX_FILESIZE_UPLOAD)
return self._(
"Attachment is too large ({size}). Maximum allowed by Telegram Bot API is {max_size}. (AT02)").format(
size=size_str, max_size=max_size_str)
return None

def process_file_obj(self, file: IO[bytes], path: Union[str, Path]) -> Union[IO[bytes], str]:
if self.channel.flag("local_tdlib_api"):
return Path(path).absolute().as_uri()
return file
3 changes: 3 additions & 0 deletions efb_telegram_master/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class ExperimentalFlagsManager(LocaleMixin):
"animated_stickers": False,
"send_to_last_chat": "warn",
"default_media_prompt": "emoji",
"api_base_url": None,
"api_base_file_url": None,
"local_tdlib_api": False,
}

def __init__(self, channel: 'TelegramChannel'):
Expand Down

0 comments on commit cdda04a

Please sign in to comment.