Add option to log in to custom puppet with shared secret

This commit is contained in:
Tulir Asokan
2019-12-15 17:10:04 +02:00
parent 39927ac6c0
commit 2ae4b23528
7 changed files with 35 additions and 9 deletions
+6
View File
@@ -154,6 +154,12 @@ bridge:
# Whether or not to use /sync to get presence, read receipts and typing notifications when using # 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. # your own Matrix account as the Matrix puppet for your Telegram account.
sync_with_custom_puppets: true sync_with_custom_puppets: true
# Shared secret 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
# Set to false to disable link previews in messages sent to Telegram. # Set to false to disable link previews in messages sent to Telegram.
telegram_link_preview: true telegram_link_preview: true
# Use inline images instead of a separate message for the caption. # Use inline images instead of a separate message for the caption.
+6 -3
View File
@@ -20,7 +20,8 @@ from telethon.errors import ( # isort: skip
AccessTokenExpiredError, AccessTokenInvalidError, FirstNameInvalidError, FloodWaitError, AccessTokenExpiredError, AccessTokenInvalidError, FirstNameInvalidError, FloodWaitError,
PasswordHashInvalidError, PhoneCodeExpiredError, PhoneCodeInvalidError, PasswordHashInvalidError, PhoneCodeExpiredError, PhoneCodeInvalidError,
PhoneNumberAppSignupForbiddenError, PhoneNumberBannedError, PhoneNumberFloodError, PhoneNumberAppSignupForbiddenError, PhoneNumberBannedError, PhoneNumberFloodError,
PhoneNumberOccupiedError, PhoneNumberUnoccupiedError, SessionPasswordNeededError) PhoneNumberOccupiedError, PhoneNumberUnoccupiedError, SessionPasswordNeededError,
PhoneNumberInvalidError)
from mautrix.types import EventID from mautrix.types import EventID
@@ -84,7 +85,7 @@ async def enter_code_register(evt: CommandEvent) -> EventID:
await evt.sender.ensure_started(even_if_no_session=True) await evt.sender.ensure_started(even_if_no_session=True)
first_name, last_name = evt.sender.command_status["full_name"] first_name, last_name = evt.sender.command_status["full_name"]
user = await evt.sender.client.sign_up(evt.args[0], first_name, last_name) user = await evt.sender.client.sign_up(evt.args[0], first_name, last_name)
asyncio.ensure_future(evt.sender.post_login(user), loop=evt.loop) asyncio.ensure_future(evt.sender.post_login(user, first_login=True), loop=evt.loop)
evt.sender.command_status = None evt.sender.command_status = None
return await evt.reply(f"Successfully registered to Telegram.") return await evt.reply(f"Successfully registered to Telegram.")
except PhoneNumberOccupiedError: except PhoneNumberOccupiedError:
@@ -166,6 +167,8 @@ async def _request_code(evt: CommandEvent, phone_number: str, next_status: Dict[
except PhoneNumberUnoccupiedError: except PhoneNumberUnoccupiedError:
return await evt.reply("That phone number has not been registered. " return await evt.reply("That phone number has not been registered. "
"Please register with `$cmdprefix+sp register <phone>`.") "Please register with `$cmdprefix+sp register <phone>`.")
except PhoneNumberInvalidError:
return await evt.reply("That phone number is not valid.")
except Exception: except Exception:
evt.log.exception("Error requesting phone code") evt.log.exception("Error requesting phone code")
return await evt.reply("Unhandled exception while requesting code. " return await evt.reply("Unhandled exception while requesting code. "
@@ -244,7 +247,7 @@ async def _sign_in(evt: CommandEvent, **sign_in_info) -> EventID:
await evt.reply(f"[{existing_user.displayname}]" await evt.reply(f"[{existing_user.displayname}]"
f"(https://matrix.to/#/{existing_user.mxid})" f"(https://matrix.to/#/{existing_user.mxid})"
" was logged out from the account.") " was logged out from the account.")
asyncio.ensure_future(evt.sender.post_login(user), loop=evt.loop) asyncio.ensure_future(evt.sender.post_login(user, first_login=True), loop=evt.loop)
evt.sender.command_status = None evt.sender.command_status = None
name = f"@{user.username}" if user.username else f"+{user.phone}" name = f"@{user.username}" if user.username else f"+{user.phone}"
return await evt.reply(f"Successfully logged in as {name}") return await evt.reply(f"Successfully logged in as {name}")
+1
View File
@@ -109,6 +109,7 @@ class Config(BaseBridgeConfig):
copy("bridge.plaintext_highlights") copy("bridge.plaintext_highlights")
copy("bridge.public_portals") copy("bridge.public_portals")
copy("bridge.sync_with_custom_puppets") copy("bridge.sync_with_custom_puppets")
copy("bridge.login_shared_secret")
copy("bridge.telegram_link_preview") copy("bridge.telegram_link_preview")
copy("bridge.inline_images") copy("bridge.inline_images")
copy("bridge.image_as_file_size") copy("bridge.image_as_file_size")
+3
View File
@@ -424,4 +424,7 @@ def init(context: 'Context') -> Iterable[Awaitable[Any]]:
Puppet.displayname_template = SimpleTemplate(config["bridge.displayname_template"], Puppet.displayname_template = SimpleTemplate(config["bridge.displayname_template"],
"displayname") "displayname")
Puppet.login_shared_secret = config["bridge.login_shared_secret"].encode("utf-8")
Puppet.login_device_name = "Telegram Bridge"
return (puppet.try_start() for puppet in Puppet.all_with_custom_mxid()) return (puppet.try_start() for puppet in Puppet.all_with_custom_mxid())
+17 -4
View File
@@ -199,14 +199,27 @@ class User(AbstractUser, BaseUser):
self.client.session.delete() self.client.session.delete()
return self return self
async def post_login(self, info: TLUser = None) -> None: async def post_login(self, info: TLUser = None, first_login: bool = False) -> None:
try: try:
await self.update_info(info) await self.update_info(info)
if not self.is_bot and config["bridge.startup_sync"]: except Exception:
self.log.exception("Failed to update telegram account info")
return
try:
puppet = pu.Puppet.get(self.tgid)
if puppet.custom_mxid != self.mxid and puppet.can_auto_login(self.mxid):
self.log.info(f"Automatically enabling custom puppet")
await puppet.switch_mxid(access_token="auto", mxid=self.mxid)
except Exception:
self.log.exception("Failed to automatically enable custom puppet")
if not self.is_bot and config["bridge.startup_sync"]:
try:
await self.sync_dialogs() await self.sync_dialogs()
await self.sync_contacts() await self.sync_contacts()
except Exception: except Exception:
self.log.exception("Failed to run post-login functions for %s", self.mxid) self.log.exception("Failed to run post-login sync")
async def update(self, update: TypeUpdate) -> bool: async def update(self, update: TypeUpdate) -> bool:
if not self.is_bot: if not self.is_bot:
+1 -1
View File
@@ -119,7 +119,7 @@ class AuthAPI(abc.ABC):
existing_user = User.get_by_tgid(user_info.id) existing_user = User.get_by_tgid(user_info.id)
if existing_user and existing_user != user: if existing_user and existing_user != user:
await existing_user.log_out() await existing_user.log_out()
asyncio.ensure_future(user.post_login(user_info), loop=self.loop) asyncio.ensure_future(user.post_login(user_info, first_login=True), loop=self.loop)
if user.command_status and user.command_status["action"] == "Login": if user.command_status and user.command_status["action"] == "Login":
user.command_status = None user.command_status = None
+1 -1
View File
@@ -42,7 +42,7 @@ setuptools.setup(
install_requires=[ install_requires=[
"aiohttp>=3.0.1,<4", "aiohttp>=3.0.1,<4",
"mautrix>=0.4.0rc2,<0.5", "mautrix>=0.4.0rc4,<0.5",
"SQLAlchemy>=1.2.3,<2", "SQLAlchemy>=1.2.3,<2",
"alembic>=1.0.0,<2", "alembic>=1.0.0,<2",
"commonmark>=0.8.1,<0.10", "commonmark>=0.8.1,<0.10",