commit b853e47d63e2d17c70e18cd647ffbb05a8569243 Author: Sebastian Hugentobler Date: Wed Nov 28 14:34:46 2018 +0100 initial commit diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..c3f7962 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,14 @@ +pipeline: + docker: + image: plugins/docker + repo: thallian/matrix-appservice-whatsapp + autotag: true + secrets: [ docker_username, docker_password ] + tags: + - ${DRONE_COMMIT_SHA} + - ${DRONE_COMMIT_BRANCH} + - latest + notify: + image: plugins/matrix + secrets: [ matrix_username, matrix_password, matrix_homeserver, matrix_roomid ] + diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d741e40 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +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/.gitignore b/.gitignore new file mode 100755 index 0000000..af0faab --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +.DS_Store +*.swp diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b5718cf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,58 @@ +FROM alpine:3.8 as builder + +RUN apk --no-cache add \ + gcc \ + musl-dev \ + python3-dev \ + zlib-dev \ + jpeg-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 + +RUN pip3 install --upgrade \ + https://github.com/tulir/mautrix-telegram/tarball/master#egg=mautrix_telegram[all] + +FROM thallian/confd-env:latest + +RUN addgroup -g 2222 matrix-bridge +RUN adduser -h /var/lib/matrix-bridge -u 2222 -D -G matrix-bridge matrix-bridge + +RUN apk --no-cache add \ + ca-certificates \ + python3 \ + ffmpeg \ + libmagic \ + zlib \ + jpeg + +COPY --from=builder /usr/lib/python3.6/site-packages /usr/lib/python3.6/site-packages + +WORKDIR /var/lib/matrix-bridge + +RUN mkdir /var/lib/matrix-bridge/data + +ADD /rootfs / + +RUN chown -R matrix-bridge:matrix-bridge /var/lib/matrix-bridge +ENV HOME /var/lib/matrix-bridge + +EXPOSE 8080 + diff --git a/README.md b/README.md new file mode 100644 index 0000000..53d65cb --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +[telegram bridge](https://github.com/tulir/mautrix-telegram) for the [matrix](http://matrix.org/) network. + +# Volumes +- `/var/lib/matrix-bridge/data` + +# Environment Variables +## SERVER_DOMAIN +Domain of the synapse server. + +## SERVER_URL +Full url to the synapse server. + +## SERVER_URL_PUBLIC +The base URL where the public-facing endpoints are available. + +## AS_TOKEN +Appservice token (from the generated registration) + +## HS_TOKEN +Homeserver token (from the generated registration) + +## DATABASE_DATASOURCE +Datasource url for sqlalchemy (sqlite and postgre are tested). + +## API_ID +Telegram API id (https://my.telegram.org/apps). + +## API_HASH +Telegram API hash (https://my.telegram.org/apps). + +## ADMIN_USER +Matrix id of the admin user. + +# Ports +- 8080 diff --git a/rootfs/etc/confd/conf.d/config.yaml.toml b/rootfs/etc/confd/conf.d/config.yaml.toml new file mode 100644 index 0000000..214f61d --- /dev/null +++ b/rootfs/etc/confd/conf.d/config.yaml.toml @@ -0,0 +1,6 @@ +[template] +src = "config.yaml.tmpl" +dest = "/var/lib/matrix-bridge/config.yaml" +uid = 2222 +gid = 2222 +mode = "0640" diff --git a/rootfs/etc/confd/templates/config.yaml.tmpl b/rootfs/etc/confd/templates/config.yaml.tmpl new file mode 100644 index 0000000..ba4b0d6 --- /dev/null +++ b/rootfs/etc/confd/templates/config.yaml.tmpl @@ -0,0 +1,276 @@ +# Homeserver details +homeserver: + # The address that this appservice can use to connect to the homeserver. + address: {{ getenv "SERVER_URL" }} + # The domain of the homeserver (for MXIDs, etc). + domain: {{ getenv "SERVER_DOMAIN" }} + # Whether or not to verify the SSL certificate of the homeserver. + # Only applies if address starts with https:// + verify_ssl: true + +# 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 + + # The hostname and port where this appservice should listen. + hostname: 0.0.0.0 + port: 8080 + # 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. + # Format examples: + # SQLite: sqlite:///filename.db + # Postgres: postgres://username:password@hostname/dbname + database: {{ getenv "DATABASE_DATASOURCE"}} + # Whether or not to use SQLAlchemy Core for common database actions. Use if the bridge is + # being bottlenecked on ORM commits. Only supported with PostgreSQL. + sqlalchemy_core_mode: false + + # 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 + # the HS database. + public: + # Whether or not the public-facing endpoints should be enabled. + enabled: true + # The prefix to use in the public-facing endpoints. + prefix: /public + # The base URL where the public-facing endpoints are available. The prefix is not added + # implicitly. + 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/). + provisioning: + # Whether or not the provisioning API should be enabled. + enabled: true + # The prefix to use in the provisioning API endpoints. + prefix: /_matrix/provision/v1 + # The shared secret to authorize users of the API. + # Set to "generate" to generate and save a new token. + shared_secret: generate + + # The unique ID of this appservice. + id: telegram + # Username of the appservice bot. + bot_username: _telegram_bot + # 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_avatar: mxc://maunium.net/tJCRmUyJDsgRNgqhOgoiHWbX + + # Authentication tokens for AS <-> HS communication. Autogenerated; do not modify. + as_token: "{{ getenv "AS_TOKEN" }}" + hs_token: "{{ getenv "HS_TOKEN" }}" + +# Bridge config +bridge: + # Localpart template of MXIDs for Telegram users. + # {userid} is replaced with the user ID of the Telegram user. + username_template: telegram_{userid} + # Localpart template of room aliases for Telegram portal rooms. + # {groupname} is replaced with the name part of the public channel/group invite link ( https://t.me/{} ) + alias_template: telegram_{groupname} + # Displayname template for Telegram users. + # {displayname} is replaced with the display name of the Telegram user. + displayname_template: '{displayname} (Telegram)' + + # Set the preferred order of user identifiers which to use in the Matrix puppet display name. + # In the (hopefully unlikely) scenario that none of the given keys are found, the numeric user + # ID is used. + # + # If the bridge is working properly, a phone number or an username should always be known, but + # the other one can very well be empty. + # + # Valid keys: + # "full name" (First and/or last name) + # "full name reversed" (Last and/or first name) + # "first name" + # "last name" + # "username" + # "phone number" + displayname_preference: + - full name + - username + - phone number + + # 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 + # 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. + sync_channel_members: true + # The maximum number of simultaneous Telegram deletions to handle. + # A large number of simultaneous redactions could put strain on your homeserver. + max_telegram_delete: 10 + # Allow logging in within Matrix. If false, the only way to log in is using the out-of-Matrix + # login website (see appservice.public config section) + allow_matrix_login: true + # Whether or not to bridge plaintext highlights. + # Only enable this if your displayname_template has some static part that the bridge can use to + # reliably identify what is a plaintext highlight. + plaintext_highlights: false + # Highlight changed/added parts in edits. Requires lxml. + highlight_edits: true + # Whether or not to make portals of publicly joinable channels/supergroups publicly joinable on Matrix. + public_portals: true + # Whether or not to fetch and handle Telegram updates at startup from the time the bridge was down. + # Currently only works for private chats and normal groups. + catch_up: 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. + sync_with_custom_puppets: true + + # 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 + + # Show message editing as a reply to the original message. + # If this is false, message edits are not shown at all, as Matrix does not support editing yet. + edits_as_replies: true + bridge_notices: + # Whether or not Matrix bot messages (type m.notice) should be bridged. + default: false + # 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: [] + # Whether to bridge Telegram bot messages as m.notices or m.texts. + bot_messages_as_notices: true + # 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). + inline_images: false + # Whether to send stickers as the new native m.sticker type or normal m.images. + # Old versions of Riot don't support the new type at all. + # Remember that proper sticker support always requires Pillow to convert webp into png. + native_stickers: true + + # The formats to use when sending messages to Telegram via the relay bot. + # + # Telegram doesn't have built-in emotes, so the m.emote format is also used for non-relaybot users. + # + # Available variables: + # $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) + # $message - The message content as HTML + message_formats: + m.text: '$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' + + # The formats to use when sending state events to Telegram via the relay bot. + # + # Variables from `message_formats` that have the `sender_` prefix are available without the prefix. + # In name_change events, `$prev_displayname` is the previous displayname. + # + # 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 + + # Filter rooms that can/can't be bridged. Can also be managed using the `filter` and + # `filter-mode` management commands. + # + # Filters do not affect direct chats. + # An empty blacklist will essentially disable the filter. + filter: + # Filter mode to use. Either "blacklist" or "whitelist". + # If the mode is "blacklist", the listed chats will never be bridged. + # If the mode is "whitelist", only the listed chats can be bridged. + mode: blacklist + # The list of group/channel IDs to filter. + list: [] + + # The prefix for commands. Only required in non-management rooms. + command_prefix: '!tg' + + # Permissions for using the bridge. + # Permitted values: + # relaybot - Only use the bridge via the relaybot, no access to commands. + # user - Relaybot level + access to commands to create bridges. + # puppeting - User level + logging in with a Telegram account. + # full - Full access to use the bridge, i.e. previous levels + Matrix login. + # admin - Full access to use the bridge and some extra administration commands. + # Permitted keys: + # * - All Matrix users + # domain - All users on that homeserver + # mxid - Specific user + permissions: + '*': relaybot + "{{ getenv "SERVER_DOMAIN" }}": full + "{{ getenv "ADMIN_USER" }}": admin + + # Options related to the message relay Telegram bot. + relaybot: + # Whether or not to allow creating portals from Telegram. + authless_portals: true + # Whether or not to allow Telegram group admins to use the bot commands. + whitelist_group_admins: true + # Whether or not to ignore incoming events sent by the relay bot. + ignore_own_incoming_events: true + # List of usernames/user IDs who are also allowed to use the bot commands. + whitelist: [] + +# Telegram config +telegram: + # Get your own API keys at https://my.telegram.org/apps + api_id: {{ getenv "API_ID" }} + api_hash: {{ getenv "API_HASH" }} + # (Optional) Create your own bot at https://t.me/BotFather + bot_token: disabled + # Telethon proxy configuration. + # You must install PySocks from pip for proxies to work. + proxy: + # Allowed types: disabled, socks4, socks5, http + type: disabled + # Proxy IP address and port. + address: 127.0.0.1 + port: 1080 + # Whether or not to perform DNS resolving remotely. + rdns: true + # Proxy authentication (optional). + username: '' + password: '' + +# Python logging configuration. +# +# See section 16.7.2 of the Python documentation for more info: +# https://docs.python.org/3.6/library/logging.config.html#configuration-dictionary-schema +logging: + version: 1 + formatters: + precise: + format: '[%(asctime)s] [%(levelname)s@%(name)s] %(message)s' + handlers: + console: + class: logging.StreamHandler + formatter: precise + loggers: + mau: + level: DEBUG + telethon: + level: DEBUG + aiohttp: + level: INFO + root: + level: DEBUG + handlers: [console] diff --git a/rootfs/etc/fix-attrs.d/01-bridge b/rootfs/etc/fix-attrs.d/01-bridge new file mode 100644 index 0000000..39e31e9 --- /dev/null +++ b/rootfs/etc/fix-attrs.d/01-bridge @@ -0,0 +1,2 @@ +/var/lib/matrix-bridge/data/ true matrix-bridge 0640 0750 + diff --git a/rootfs/etc/services.d/telegram-bridge/run b/rootfs/etc/services.d/telegram-bridge/run new file mode 100644 index 0000000..a1b3692 --- /dev/null +++ b/rootfs/etc/services.d/telegram-bridge/run @@ -0,0 +1,3 @@ +#!/usr/bin/with-contenv sh + +#s6-setuidgid matrix-bridge mautrix-whatsapp -c /var/lib/matrix-bridge/config.yaml -r /var/lib/matrix-bridge/whatsapp-registration.yaml