Pārlūkot izejas kodu

Fix bugs and add command to start PMs

Tulir Asokan 4 gadi atpakaļ
vecāks
revīzija
9853392c66

+ 1 - 0
mautrix_signal/commands/__init__.py

@@ -1,2 +1,3 @@
 from .auth import SECTION_AUTH
 from .auth import SECTION_AUTH
 from .conn import SECTION_CONNECTION
 from .conn import SECTION_CONNECTION
+from .signal import SECTION_CREATING_PORTALS

+ 49 - 0
mautrix_signal/commands/signal.py

@@ -0,0 +1,49 @@
+# mautrix-signal - A Matrix-Signal puppeting bridge
+# Copyright (C) 2020 Tulir Asokan
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+from mautrix.bridge.commands import HelpSection, command_handler
+from mausignald.types import Address
+
+from .. import puppet as pu, portal as po
+from .typehint import CommandEvent
+
+SECTION_CREATING_PORTALS = HelpSection("Creating portals", 20, "")
+
+remove_extra_chars = str.maketrans("", "", " .,-()")
+
+
+@command_handler(needs_auth=True, management_only=False, help_section=SECTION_CREATING_PORTALS,
+                 help_text="Open a private chat portal with a specific phone number",
+                 help_args="<_phone_>")
+async def pm(evt: CommandEvent) -> None:
+    if len(evt.args) == 0 or not evt.args[0].startswith("+"):
+        await evt.reply("**Usage:** `$cmdprefix+sp pm <phone>` "
+                        "(enter phone number in international format)")
+        return
+    phone = "".join(evt.args).translate(remove_extra_chars)
+    if not phone[1:].isdecimal():
+        await evt.reply("**Usage:** `$cmdprefix+sp pm <phone>` "
+                        "(enter phone number in international format)")
+        return
+    puppet = await pu.Puppet.get_by_address(Address(number=phone))
+    portal = await po.Portal.get_by_chat_id(puppet.address, receiver=evt.sender.username,
+                                            create=True)
+    if portal.mxid:
+        await evt.reply(f"You already have a private chat with {puppet.name}: "
+                        f"[{portal.mxid}](https://matrix.to/#/{portal.mxid})")
+        await portal.main_intent.invite_user(portal.mxid, evt.sender.mxid)
+        return
+    await portal.create_matrix_room(evt.sender, puppet.address)
+    await evt.reply(f"Created a portal room with [{puppet.name}](https://matrix.to/#/{puppet.mxid}) and invited you to it")

+ 15 - 7
mautrix_signal/puppet.py

@@ -24,6 +24,7 @@ from mausignald.types import Address, Contact, Profile
 from mautrix.bridge import BasePuppet
 from mautrix.bridge import BasePuppet
 from mautrix.appservice import IntentAPI
 from mautrix.appservice import IntentAPI
 from mautrix.types import UserID, SyncToken, RoomID
 from mautrix.types import UserID, SyncToken, RoomID
+from mautrix.errors import MForbidden
 from mautrix.util.simple_template import SimpleTemplate
 from mautrix.util.simple_template import SimpleTemplate
 
 
 from .db import Puppet as DBPuppet
 from .db import Puppet as DBPuppet
@@ -61,7 +62,7 @@ class Puppet(DBPuppet, BasePuppet):
         super().__init__(uuid=uuid, number=number, name=name, uuid_registered=uuid_registered,
         super().__init__(uuid=uuid, number=number, name=name, uuid_registered=uuid_registered,
                          number_registered=number_registered, custom_mxid=custom_mxid,
                          number_registered=number_registered, custom_mxid=custom_mxid,
                          access_token=access_token, next_batch=next_batch, base_url=base_url)
                          access_token=access_token, next_batch=next_batch, base_url=base_url)
-        self.log = self.log.getChild(str(uuid) or number)
+        self.log = self.log.getChild(str(uuid) if uuid else number)
 
 
         self.default_mxid = self.get_mxid_from_id(self.address)
         self.default_mxid = self.get_mxid_from_id(self.address)
         self.default_mxid_intent = self.az.intent.user(self.default_mxid)
         self.default_mxid_intent = self.az.intent.user(self.default_mxid)
@@ -131,17 +132,24 @@ class Puppet(DBPuppet, BasePuppet):
         self.default_mxid = self.get_mxid_from_id(self.address)
         self.default_mxid = self.get_mxid_from_id(self.address)
         self.default_mxid_intent = self.az.intent.user(self.default_mxid)
         self.default_mxid_intent = self.az.intent.user(self.default_mxid)
         self.intent = self._fresh_intent()
         self.intent = self._fresh_intent()
-        await self.intent.ensure_registered()
+        await self.default_mxid_intent.ensure_registered()
         if self.name:
         if self.name:
-            await self.intent.set_displayname(self.name)
-        self.log = self.log.getChild(str(uuid))
-        self.log.debug(f"Migrating memberships {prev_intent.mxid} -> {self.default_mxid_intent}")
-        for room_id in await prev_intent.get_joined_rooms():
+            await self.default_mxid_intent.set_displayname(self.name)
+        self.log = Puppet.log.getChild(str(uuid))
+        self.log.debug(f"Migrating memberships {prev_intent.mxid}"
+                       f" -> {self.default_mxid_intent.mxid}")
+        try:
+            joined_rooms = await prev_intent.get_joined_rooms()
+        except MForbidden as e:
+            self.log.debug(f"Got MForbidden ({e.message}) when getting joined rooms of old mxid, "
+                           "assuming there are no rooms to rejoin")
+            return
+        for room_id in joined_rooms:
             await prev_intent.invite_user(room_id, self.default_mxid)
             await prev_intent.invite_user(room_id, self.default_mxid)
             await prev_intent.leave_room(room_id)
             await prev_intent.leave_room(room_id)
             await self.default_mxid_intent.join_room_by_id(room_id)
             await self.default_mxid_intent.join_room_by_id(room_id)
 
 
-    async def update_info(self, info: Union[Profile, Contact]) -> None:
+    async def update_info(self, info: Union[Profile, Contact, Address]) -> None:
         if isinstance(info, (Contact, Address)):
         if isinstance(info, (Contact, Address)):
             address = info.address if isinstance(info, Contact) else info
             address = info.address if isinstance(info, Contact) else info
             if address.uuid and not self.uuid:
             if address.uuid and not self.uuid:

+ 1 - 1
requirements.txt

@@ -4,5 +4,5 @@ commonmark>=0.8,<0.10
 aiohttp>=3,<3.7
 aiohttp>=3,<3.7
 yarl>=1,<1.6
 yarl>=1,<1.6
 attrs>=19.1
 attrs>=19.1
-mautrix==0.8.0.beta9
+mautrix==0.8.0rc1
 asyncpg>=0.20,<0.22
 asyncpg>=0.20,<0.22