diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index d741e40..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-root = true
-
-[*]
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-indent_style = space
-indent_size = 4
diff --git a/Dockerfile b/Dockerfile
index 7b18b0c..d930e2f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,88 +1,87 @@
-FROM alpine:3.14 as builder
+FROM alpine:3.15 as builder
-ENV VERSION=730f6bab6fc0ca4077f3b09d866ad50767df9086
+ENV VERSION=0.11.2
RUN apk --no-cache add \
+ sed \
gcc \
- g++ \
- musl-dev \
- python3-dev \
- zlib-dev \
- jpeg-dev \
- libffi-dev \
- postgresql-dev \
+ g++ \
+ git \
+ musl-dev \
+ libffi-dev \
+ python3-dev \
py3-pip \
- py3-aiohttp \
- py3-sqlalchemy \
- py3-magic \
- py3-lxml \
- py3-attrs \
- py3-chardet \
- py3-multidict \
- py3-yarl \
- py3-idna-ssl \
- py3-mako \
- py3-dateutil \
- py3-future \
- py3-async-timeout \
- py3-rsa \
- py3-decorator \
- py3-idna \
- py3-markupsafe \
- py3-six \
- py3-asn1 \
- py3-numpy \
- py3-psycopg2 \
- py3-wheel \
- olm-dev
+ py3-wheel \
+ py3-brotli \
+ py3-olm \
+ py3-qrcode \
+ py3-pillow \
+ py3-phonenumbers \
+ py3-unpaddedbase64 \
+ py3-pycryptodome \
+ py3-pyaes \
+ py3-rsa \
+ py3-cparser \
+ py3-cffi \
+ py3-decorator \
+ py3-tqdm \
+ py3-numpy \
+ py3-future \
+ py3-asn1 \
+ py3-ruamel.yaml \
+ py3-magic \
+ py3-commonmark \
+ py3-aiohttp \
+ py3-yarl \
+ py3-mako \
+ py3-setuptools
+
+RUN git clone -b v0.25.0 --recursive https://github.com/MagicStack/asyncpg.git
+WORKDIR /asyncpg
+RUN sed -ie '1,3d' pyproject.toml
+RUN python3 setup.py install --prefix=/install
+RUN pip3 install --prefix=/install mautrix-telegram[all]==$VERSION
-RUN mkdir /tmp/mautrix-telegram
-RUN wget -qO- https://github.com/tulir/mautrix-telegram/archive/$VERSION.tar.gz | tar -xz --strip 1 -C /tmp/mautrix-telegram
-RUN cd /tmp/mautrix-telegram && pip3 install -r requirements.txt -r optional-requirements.txt && pip3 install .
FROM thallian/confd-env:latest
ENV FFMPEG_BINARY=/usr/bin/ffmpeg
+COPY --from=builder /install /py-pkgs
+
RUN addgroup -g 2222 matrix-bridge
RUN adduser -h /var/lib/matrix-bridge -u 2222 -D -G matrix-bridge matrix-bridge
-COPY --from=builder /usr/lib/python3.9/site-packages /usr/lib/python3.9/site-packages
-COPY --from=builder /usr/bin/alembic /usr/bin/alembic
-COPY --from=builder /tmp/mautrix-telegram/alembic /var/lib/matrix-bridge/alembic
-COPY --from=builder /tmp/mautrix-telegram/alembic.ini /var/lib/matrix-bridge/alembic.ini
-
RUN apk --no-cache add \
ca-certificates \
- python3 \
ffmpeg \
- libmagic \
- zlib \
- jpeg \
libffi \
- postgresql-dev \
- py3-aiohttp \
- py3-sqlalchemy \
- py3-magic \
- py3-lxml \
- py3-attrs \
- py3-chardet \
- py3-multidict \
- py3-yarl \
- py3-idna-ssl \
- py3-mako \
- py3-dateutil \
- py3-future \
- py3-async-timeout \
- py3-rsa \
- py3-decorator \
- py3-idna \
- py3-markupsafe \
- py3-six \
- py3-asn1 \
- py3-numpy \
- py3-psycopg2 \
- olm
+ python3 \
+ py3-brotli \
+ py3-olm \
+ py3-qrcode \
+ py3-pillow \
+ py3-phonenumbers \
+ py3-unpaddedbase64 \
+ py3-pycryptodome \
+ py3-pyaes \
+ py3-rsa \
+ py3-cparser \
+ py3-cffi \
+ py3-decorator \
+ py3-tqdm \
+ py3-numpy \
+ py3-future \
+ py3-asn1 \
+ py3-ruamel.yaml \
+ py3-magic \
+ py3-commonmark \
+ py3-aiohttp \
+ py3-yarl \
+ py3-mako \
+ py3-setuptools
+
+ENV PYTHONPATH=/usr/lib/python3.9/site-packages:/py-pkgs/lib/python3.9/site-packages/
WORKDIR /var/lib/matrix-bridge
diff --git a/rootfs/etc/confd/templates/config.yaml.tmpl b/rootfs/etc/confd/templates/config.yaml.tmpl
index 3ce8608..7a1bf1e 100644
--- a/rootfs/etc/confd/templates/config.yaml.tmpl
+++ b/rootfs/etc/confd/templates/config.yaml.tmpl
@@ -7,29 +7,44 @@ homeserver:
# Whether or not to verify the SSL certificate of the homeserver.
# Only applies if address starts with https://
verify_ssl: true
+ asmux: false
+ # Number of retries for all HTTP requests if the homeserver isn't reachable.
+ http_retry_count: 4
+ # The URL to push real-time bridge status to.
+ # If set, the bridge will make POST requests to this URL whenever a user's Telegram connection state changes.
+ # The bridge will use the appservice as_token to authorize requests.
+ status_endpoint: null
+ # Endpoint for reporting per-message status.
+ message_send_checkpoint_endpoint: null
# Application service host/registration related details
# Changing these values requires regeneration of the registration.
appservice:
# The address that the homeserver can use to connect to this appservice.
- address: http://{{getenv "HOSTNAME"}}:8080
+ address: http://{{getenv "HOSTNAME"}}:29317
# When using https:// the TLS certificate and key files for the address.
tls_cert: false
tls_key: false
# The hostname and port where this appservice should listen.
hostname: 0.0.0.0
- port: 8080
+ port: 29317
# The maximum body size of appservice API requests (from the homeserver) in mebibytes
# Usually 1 is enough, but on high-traffic bridges you might need to increase this to avoid 413s
max_body_size: 1
- # The full URI to the database. SQLite and Postgres are fully supported.
- # Other DBMSes supported by SQLAlchemy may or may not work.
+ # The full URI to the database. SQLite and Postgres are supported.
# Format examples:
# SQLite: sqlite:///filename.db
# Postgres: postgres://username:password@hostname/dbname
database: {{ getenv "DATABASE_DATASOURCE"}}
+ # Additional arguments for asyncpg.create_pool() or sqlite3.connect()
+ # https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.pool.create_pool
+ # https://docs.python.org/3/library/sqlite3.html#sqlite3.connect
+ # For sqlite, min_size is used as the connection thread pool size and max_size is ignored.
+ database_opts:
+ min_size: 1
+ max_size: 10
# Public part of web server for out-of-Matrix interaction with the bridge.
# Used for things like login if the user wants to make sure the 2FA password isn't stored in
@@ -44,7 +59,7 @@ appservice:
external: {{ getenv "SERVER_URL_PUBLIC" }}
# Provisioning API part of the web server for automated portal creation and fetching information.
- # Used by things like Dimension (https://dimension.t2bot.io/).
+ # Used by things like mautrix-manager (https://github.com/tulir/mautrix-manager).
provisioning:
# Whether or not the provisioning API should be enabled.
enabled: true
@@ -57,17 +72,16 @@ appservice:
# The unique ID of this appservice.
id: telegram
# Username of the appservice bot.
- bot_username: _telegram_bot
+ bot_username: telegrambot
# Display name and avatar for bot. Set to "remove" to remove display name/avatar, leave empty
# to leave display name/avatar as-is.
- bot_displayname: Telegram Bridge Bot
+ bot_displayname: Telegram bridge bot
bot_avatar: mxc://maunium.net/tJCRmUyJDsgRNgqhOgoiHWbX
- # Community ID for bridged users (changes registration file) and rooms.
- # Must be created manually.
- #
- # Example: "+telegram:example.com". Set to false to disable.
- community_id: false
+ # Whether or not to receive ephemeral events via appservice transactions.
+ # Requires MSC2409 support (i.e. Synapse 1.22+).
+ # You should disable bridge -> sync_with_custom_puppets when this is enabled.
+ ephemeral_events: false
# Authentication tokens for AS <-> HS communication. Autogenerated; do not modify.
as_token: "{{ getenv "AS_TOKEN" }}"
@@ -129,8 +143,8 @@ bridge:
# Maximum number of members to sync per portal when starting up. Other members will be
# synced when they send messages. The maximum is 10000, after which the Telegram server
# will not send any more members.
- # Defaults to no local limit (-> limited to 10000 by server)
- max_initial_member_sync: -1
+ # -1 means no limit (which means it's limited to 10000 by the server)
+ max_initial_member_sync: 100
# Whether or not to sync the member list in channels.
# If no channel admins have logged into the bridge, the bridge won't be able to sync the member
# list regardless of this setting.
@@ -142,7 +156,10 @@ bridge:
startup_sync: true
# Number of most recently active dialogs to check when syncing chats.
# Set to 0 to remove limit.
- sync_dialog_limit: 30
+ sync_update_limit: 0
+ # Number of most recently active dialogs to create portals for when syncing chats.
+ # Set to 0 to remove limit.
+ sync_create_limit: 30
# Whether or not to sync and create portals for direct chats at startup.
sync_direct_chats: false
# The maximum number of simultaneous Telegram deletions to handle.
@@ -160,27 +177,43 @@ bridge:
plaintext_highlights: false
# Whether or not to make portals of publicly joinable channels/supergroups publicly joinable on Matrix.
public_portals: true
- # Whether or not to use /sync to get presence, read receipts and typing notifications when using
- # your own Matrix account as the Matrix puppet for your Telegram account.
+ # Whether or not to use /sync to get presence, read receipts and typing notifications
+ # when double puppeting is enabled
sync_with_custom_puppets: true
- # Shared secret for https://github.com/devture/matrix-synapse-shared-secret-auth
+ # Whether or not to update the m.direct account data event when double puppeting is enabled.
+ # Note that updating the m.direct event is not atomic (except with mautrix-asmux)
+ # and is therefore prone to race conditions.
+ sync_direct_chat_list: false
+ # Servers to always allow double puppeting from
+ double_puppet_server_map:
+ example.com: https://example.com
+ # Allow using double puppeting from any server with a valid client .well-known file.
+ double_puppet_allow_discovery: false
+ # Shared secrets for https://github.com/devture/matrix-synapse-shared-secret-auth
#
# If set, custom puppets will be enabled automatically for local users
# instead of users having to find an access token and run `login-matrix`
# manually.
- login_shared_secret: null
+ # If using this for other servers than the bridge's server,
+ # you must also set the URL in the double_puppet_server_map.
+ login_shared_secret_map:
+ example.com: foobar
# Set to false to disable link previews in messages sent to Telegram.
telegram_link_preview: true
+ # Whether or not the !tg join command should do a HTTP request
+ # to resolve redirects in invite links.
+ invite_link_resolve: false
# Use inline images instead of a separate message for the caption.
- # N.B. Inline images are not supported on all clients (e.g. Riot iOS).
+ # N.B. Inline images are not supported on all clients (e.g. Element iOS/Android).
inline_images: false
# Maximum size of image in megabytes before sending to Telegram as a document.
image_as_file_size: 10
- # Maximum size of Telegram documents in megabytes to bridge.
- max_document_size: 100
+ # Maximum number of pixels in an image before sending to Telegram as a document. Defaults to 1280x1280 = 1638400.
+ image_as_file_pixels: 1638400
# Enable experimental parallel file transfer, which makes uploads/downloads much faster by
# streaming from/to Matrix and using many connections for Telegram.
# Note that generating HQ thumbnails for videos is not possible with streamed transfers.
+ # This option uses internal Telethon implementation details and may break with minor updates.
parallel_file_transfer: false
# Whether or not created rooms should have federation enabled.
# If false, created portal rooms will never be federated.
@@ -190,27 +223,37 @@ bridge:
# Format to which animated stickers should be converted.
# disable - No conversion, send as-is (gzipped lottie)
# png - converts to non-animated png (fastest),
- # gif - converts to animated gif, but loses transparency
+ # gif - converts to animated gif
# webm - converts to webm video, requires ffmpeg executable with vp9 codec and webm container support
target: gif
# Arguments for converter. All converters take width and height.
- # GIF converter takes background as a hex color.
args:
width: 256
height: 256
- background: "020202" # only for gif
- fps: 30 # only for webm
- # End-to-bridge encryption support options. These require matrix-nio to be installed with pip
- # and login_shared_secret to be configured in order to get a device for the bridge bot.
+ fps: 25 # only for webm and gif (2, 5, 10, 20 or 25 recommended)
+ # End-to-bridge encryption support options.
#
- # Additionally, https://github.com/matrix-org/synapse/pull/5758 is required if using a normal
- # application service.
+ # See https://docs.mau.fi/bridges/general/end-to-bridge-encryption.html for more info.
encryption:
# Allow encryption, work in group chat rooms with e2ee enabled
- allow: false
+ allow: true
# Default to encryption, force-enable encryption in all portals the bridge creates
# This will cause the bridge bot to be in private chats for the encryption to work properly.
- default: false
+ default: true
+ # Database for the encryption data. If set to `default`, will use the appservice database.
+ database: default
+ # Options for automatic key sharing.
+ key_sharing:
+ # Enable key sharing? If enabled, key requests for rooms where users are in will be fulfilled.
+ # You must use a client that supports requesting keys from other users to use this feature.
+ allow: true
+ # Require the requesting device to have a valid cross-signing signature?
+ # This doesn't require that the bridge has verified the device, only that the user has verified it.
+ # Not yet implemented.
+ require_cross_signing: false
+ # Require devices to be verified by the bridge?
+ # Verification by the bridge is not yet implemented.
+ require_verification: true
# Whether or not to explicitly set the avatar and room name for private
# chat portal rooms. This will be implicitly enabled if encryption.default is true.
private_chat_portal_meta: false
@@ -223,6 +266,48 @@ bridge:
# This field will automatically be changed back to false after it,
# except if the config file is not writable.
resend_bridge_info: false
+ # When using double puppeting, should muted chats be muted in Matrix?
+ mute_bridging: false
+ # When using double puppeting, should pinned chats be moved to a specific tag in Matrix?
+ # The favorites tag is `m.favourite`.
+ pinned_tag: null
+ # Same as above for archived chats, the low priority tag is `m.lowpriority`.
+ archive_tag: null
+ # Whether or not mute status and tags should only be bridged when the portal room is created.
+ tag_only_on_create: true
+ # Should leaving the room on Matrix make the user leave on Telegram?
+ bridge_matrix_leave: true
+ # Should the user be kicked out of all portals when logging out of the bridge?
+ kick_on_logout: true
+ # Settings for backfilling messages from Telegram.
+ backfill:
+ # Whether or not the Telegram ghosts of logged in Matrix users should be
+ # invited to private chats when backfilling history from Telegram. This is
+ # usually needed to prevent rate limits and to allow timestamp massaging.
+ invite_own_puppet: true
+ # Maximum number of messages to backfill without using a takeout.
+ # The first time a takeout is used, the user has to manually approve it from a different
+ # device. If initial_limit or missed_limit are higher than this value, the bridge will ask
+ # the user to accept the takeout after logging in before syncing any chats.
+ takeout_limit: 100
+ # Maximum number of messages to backfill initially.
+ # Set to 0 to disable backfilling when creating portal, or -1 to disable the limit.
+ #
+ # N.B. Initial backfill will only start after member sync. Make sure your
+ # max_initial_member_sync is set to a low enough value so it doesn't take forever.
+ initial_limit: 0
+ # Maximum number of messages to backfill if messages were missed while the bridge was
+ # disconnected. Note that this only works for logged in users and only if the chat isn't
+ # older than sync_update_limit
+ # Set to 0 to disable backfilling missed messages.
+ missed_limit: 50
+ # If using double puppeting, should notifications be disabled
+ # while the initial backfill is in progress?
+ disable_notifications: false
+ # Whether or not to enable backfilling in normal groups.
+ # Normal groups have numerous technical problems in Telegram, and backfilling normal groups
+ # will likely cause problems if there are multiple Matrix users in the group.
+ normal_groups: false
# Overrides for base power levels.
initial_power_level_overrides:
@@ -237,19 +322,12 @@ bridge:
# List of user IDs for whom the previous flag is flipped.
# e.g. if bridge_notices.default is false, notices from other users will not be bridged, but
# notices from users listed here will be bridged.
- exceptions:
- - "@importantbot:example.com"
-
- # Some config options related to Telegram message deduplication.
- # The default values are usually fine, but some debug messages/warnings might recommend you
- # change these.
- deduplication:
- # Whether or not to check the database if the message about to be sent is a duplicate.
- pre_db_check: false
- # The number of latest events to keep when checking for duplicates.
- # You might need to increase this on high-traffic bridge instances.
- cache_queue_length: 20
+ exceptions: []
+ # An array of possible values for the $distinguisher variable in message formats.
+ # Each user gets one of the values here, based on a hash of their user ID.
+ # If the array is empty, the $distinguisher variable will also be empty.
+ relay_user_distinguishers: ["🟦", "🟣", "🟩", "⭕️", "🔶", "⬛️", "🔵", "🟢"]
# The formats to use when sending messages to Telegram via the relay bot.
# Text msgtypes (m.text, m.notice and m.emote) support HTML, media msgtypes don't.
#
@@ -257,16 +335,17 @@ bridge:
# $sender_displayname - The display name of the sender (e.g. Example User)
# $sender_username - The username (Matrix ID localpart) of the sender (e.g. exampleuser)
# $sender_mxid - The Matrix ID of the sender (e.g. @exampleuser:example.com)
+ # $distinguisher - A random string from the options in the relay_user_distinguishers array.
# $message - The message content
message_formats:
- m.text: "$sender_displayname: $message"
- m.notice: "$sender_displayname: $message"
- m.emote: "* $sender_displayname $message"
- m.file: "$sender_displayname sent a file: $message"
- m.image: "$sender_displayname sent an image: $message"
- m.audio: "$sender_displayname sent an audio file: $message"
- m.video: "$sender_displayname sent a video: $message"
- m.location: "$sender_displayname sent a location: $message"
+ m.text: "$distinguisher $sender_displayname: $message"
+ m.notice: "$distinguisher $sender_displayname: $message"
+ m.emote: "* $distinguisher $sender_displayname $message"
+ m.file: "$distinguisher $sender_displayname sent a file: $message"
+ m.image: "$distinguisher $sender_displayname sent an image: $message"
+ m.audio: "$distinguisher $sender_displayname sent an audio file: $message"
+ m.video: "$distinguisher $sender_displayname sent a video: $message"
+ m.location: "$distinguisher $sender_displayname sent a location: $message"
# Telegram doesn't have built-in emotes, this field specifies how m.emote's from authenticated
# users are sent to telegram. All fields in message_formats are supported. Additionally, the
# Telegram user info is available in the following variables:
@@ -282,9 +361,9 @@ bridge:
#
# Set format to an empty string to disable the messages for that event.
state_event_formats:
- join: "$displayname joined the room."
- leave: "$displayname left the room."
- name_change: "$prev_displayname changed their name to $displayname"
+ join: "$distinguisher $displayname joined the room."
+ leave: "$distinguisher $displayname left the room."
+ name_change: "$distinguisher $prev_displayname changed their name to $distinguisher $displayname"
# Filter rooms that can/can't be bridged. Can also be managed using the `filter` and
# `filter-mode` management commands.
@@ -302,6 +381,21 @@ bridge:
# The prefix for commands. Only required in non-management rooms.
command_prefix: "!tg"
+ # Messages sent upon joining a management room.
+ # Markdown is supported. The defaults are listed below.
+ management_room_text:
+ # Sent when joining a room.
+ welcome: "Hello, I'm a Telegram bridge bot."
+ # Sent when joining a management room and the user is already logged in.
+ welcome_connected: "Use `help` for help."
+ # Sent when joining a management room and the user is not logged in.
+ welcome_unconnected: "Use `help` for help or `login` to log in."
+ # Optional extra text sent when joining a management room.
+ additional_help: ""
+
+ # Send each message separately (for readability in some clients)
+ management_room_multiple_messages: false
+
# Permissions for using the bridge.
# Permitted values:
# relaybot - Only use the bridge via the relaybot, no access to commands.
@@ -314,11 +408,10 @@ bridge:
# domain - All users on that homeserver
# mxid - Specific user
permissions:
- '*': relaybot
+ "*": "relaybot"
"{{ getenv "SERVER_DOMAIN" }}": full
"{{ getenv "ADMIN_USER" }}": admin
-
# Options related to the message relay Telegram bot.
relaybot:
private_chat:
@@ -428,12 +521,6 @@ logging:
normal:
format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s"
handlers:
- file:
- class: logging.handlers.RotatingFileHandler
- formatter: normal
- filename: ./mautrix-telegram.log
- maxBytes: 10485760
- backupCount: 10
console:
class: logging.StreamHandler
formatter: colored
@@ -446,4 +533,4 @@ logging:
level: INFO
root:
level: DEBUG
- handlers: [file, console]
+ handlers: [console]
diff --git a/rootfs/etc/cont-init.d/02-alembic b/rootfs/etc/cont-init.d/02-alembic
deleted file mode 100644
index 5e021eb..0000000
--- a/rootfs/etc/cont-init.d/02-alembic
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/with-contenv sh
-
-s6-setuidgid matrix-bridge alembic -x config=/var/lib/matrix-bridge/config.yaml upgrade head
diff --git a/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/dependencies b/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/dependencies
new file mode 100644
index 0000000..7ba7514
--- /dev/null
+++ b/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/dependencies
@@ -0,0 +1 @@
+confd
diff --git a/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/run b/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/run
new file mode 100644
index 0000000..1a7057c
--- /dev/null
+++ b/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec python3 -m mautrix_telegram --config /var/lib/matrix-bridge/config.yaml
diff --git a/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/type b/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/type
new file mode 100644
index 0000000..5883cff
--- /dev/null
+++ b/rootfs/etc/s6-overlay/s6-rc.d/telegram-bridge/type
@@ -0,0 +1 @@
+longrun
diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/telegram-bridge b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/telegram-bridge
new file mode 100644
index 0000000..e69de29
diff --git a/rootfs/etc/services.d/telegram-bridge/run b/rootfs/etc/services.d/telegram-bridge/run
deleted file mode 100644
index 0d3a858..0000000
--- a/rootfs/etc/services.d/telegram-bridge/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/with-contenv sh
-
-s6-setuidgid matrix-bridge python3 -m mautrix_telegram -c /var/lib/matrix-bridge/config.yaml