Example #1
0
def migrate_state_store():
    conn = op.get_bind()
    session: orm.Session = orm.sessionmaker(bind=conn)()

    try:
        with open("mx-state.json") as file:
            data = json.load(file)
    except FileNotFoundError:
        return
    if not data:
        return
    registrations = data.get("registrations", [])

    mxtg_config_path = context.get_x_argument(as_dictionary=True).get(
        "config", "config.yaml")
    mxtg_config = Config(mxtg_config_path, None, None)
    mxtg_config.load()

    username_template = mxtg_config.get("bridge.username_template",
                                        "telegram_{userid}")
    hs_domain = mxtg_config["homeserver.domain"]
    localpart = username_template.format(userid="(.+)")
    mxid_regex = re.compile("@{}:{}".format(localpart, hs_domain))
    for user in registrations:
        match = mxid_regex.match(user)
        if not match:
            continue

        puppet = session.query(Puppet).get(match.group(1))
        if not puppet:
            continue

        puppet.matrix_registered = True
        session.merge(puppet)
    session.commit()

    user_profiles = [
        UserProfile(room_id=room,
                    user_id=user,
                    membership=member.get("membership", "leave"),
                    displayname=member.get("displayname", None),
                    avatar_url=member.get("avatar_url", None))
        for room, members in data.get("members", {}).items()
        for user, member in members.items()
    ]
    session.add_all(user_profiles)
    session.commit()

    room_state = [
        RoomState(room_id=room, power_levels=json.dumps(levels))
        for room, levels in data.get("power_levels", {}).items()
    ]
    session.add_all(room_state)
    session.commit()
Example #2
0
def context(request: FixtureRequest) -> Context:
    """Returns a Context with mocked Attributes.

    Uses the attribute cls.config as Config.
    """
    # Config(path, registration_path, base_path)
    config = getattr(request.cls, 'config', Config("", "", ""))
    return Context(az=Mock(),
                   config=config,
                   loop=Mock(),
                   session_container=Mock(),
                   bot=Mock())
Example #3
0
class TestCommandEvent:
    config = Config("", "", "")
    config["bridge.command_prefix"] = "tg"
    config["bridge.permissions"] = {"*": "noperm"}

    def test_reply(self, command_processor: CommandProcessor,
                   mocker: MockFixture) -> None:
        mocker.patch("mautrix_telegram.user.config", self.config)

        evt = CommandEvent(
            processor=command_processor,
            room_id=RoomID("#mock_room:example.org"),
            event_id=EventID("$H45H:example.org"),
            sender=u.User(UserID("@sender:example.org")),
            command="help",
            args=[],
            is_management=True,
            is_portal=False,
        )

        mock_az = command_processor.az

        message = "**This** <i>was</i><br/><strong>all</strong>fun*!"

        # html, no markdown
        evt.reply(message, allow_html=True, render_markdown=False)
        mock_az.intent.send_notice.assert_called_with(
            RoomID("#mock_room:example.org"),
            "**This** <i>was</i><br/><strong>all</strong>fun*!",
            html="**This** <i>was</i><br/><strong>all</strong>fun*!\n",
        )

        # html, markdown (default)
        evt.reply(message, allow_html=True, render_markdown=True)
        mock_az.intent.send_notice.assert_called_with(
            RoomID("#mock_room:example.org"),
            "**This** <i>was</i><br/><strong>all</strong>fun*!",
            html=("<p><strong>This</strong> <i>was</i><br/>"
                  "<strong>all</strong>fun*!</p>\n"),
        )

        # no html, no markdown
        evt.reply(message, allow_html=False, render_markdown=False)
        mock_az.intent.send_notice.assert_called_with(
            RoomID("#mock_room:example.org"),
            "**This** <i>was</i><br/><strong>all</strong>fun*!",
            html=None,
        )

        # no html, markdown
        evt.reply(message, allow_html=False, render_markdown=True)
        mock_az.intent.send_notice.assert_called_with(
            RoomID("#mock_room:example.org"),
            "**This** <i>was</i><br/><strong>all</strong>fun*!",
            html="<p><strong>This</strong> &lt;i&gt;was&lt;/i&gt;&lt;br/&gt;"
            "&lt;strong&gt;all&lt;/strong&gt;fun*!</p>\n")

    def test_reply_with_cmdprefix(self, command_processor: CommandProcessor,
                                  mocker: MockFixture) -> None:
        mocker.patch("mautrix_telegram.user.config", self.config)

        evt = CommandEvent(
            processor=command_processor,
            room_id=RoomID("#mock_room:example.org"),
            event_id=EventID("$H45H:example.org"),
            sender=u.User(UserID("@sender:example.org")),
            command="help",
            args=[],
            is_management=False,
            is_portal=False,
        )

        mock_az = command_processor.az

        evt.reply("$cmdprefix+sp ....$cmdprefix+sp...$cmdprefix $cmdprefix",
                  allow_html=False,
                  render_markdown=False)

        mock_az.intent.send_notice.assert_called_with(
            RoomID("#mock_room:example.org"),
            "tg ....tg+sp...tg tg",
            html=None,
        )

    def test_reply_with_cmdprefix_in_management_room(
            self, command_processor: CommandProcessor,
            mocker: MockFixture) -> None:
        mocker.patch("mautrix_telegram.user.config", self.config)

        evt = CommandEvent(
            processor=command_processor,
            room_id=RoomID("#mock_room:example.org"),
            event_id=EventID("$H45H:example.org"),
            sender=u.User(UserID("@sender:example.org")),
            command="help",
            args=[],
            is_management=True,
            is_portal=False,
        )

        mock_az = command_processor.az

        evt.reply(
            "$cmdprefix+sp ....$cmdprefix+sp...$cmdprefix $cmdprefix",
            allow_html=True,
            render_markdown=True,
        )

        mock_az.intent.send_notice.assert_called_with(
            RoomID("#mock_room:example.org"),
            "....tg+sp...tg tg",
            html="<p>....tg+sp...tg tg</p>\n",
        )
Example #4
0
class TestCommandProcessor:
    config = Config("", "", "")
    config["bridge.command_prefix"] = "tg"
    config["bridge.permissions"] = {"*": "relaybot"}

    @pytest.mark.asyncio
    async def test_handle(self, command_processor: CommandProcessor,
                          boolean2: Tuple[bool,
                                          bool], mocker: MockFixture) -> None:
        mocker.patch('mautrix_telegram.user.config', self.config)
        mocker.patch('mautrix.bridge.commands.handler.command_handlers', {
            "help": AsyncMock(),
            "unknown-command": AsyncMock()
        })

        sender = u.User(UserID("@sender:example.org"))

        result = await command_processor.handle(
            room_id=RoomID("#mock_room:example.org"),
            event_id=EventID("$H45H:example.org"),
            sender=sender,
            command="hElp",
            args=[],
            is_management=boolean2[0],
            is_portal=boolean2[1])

        assert result is None
        command_handlers = mautrix.bridge.commands.handler.command_handlers
        command_handlers["help"].mock.assert_called_once()  # type: ignore

    @pytest.mark.asyncio
    async def test_handle_unknown_command(self,
                                          command_processor: CommandProcessor,
                                          boolean2: Tuple[bool, bool],
                                          mocker: MockFixture) -> None:
        mocker.patch('mautrix_telegram.user.config', self.config)
        mocker.patch('mautrix.bridge.commands.handler.command_handlers', {
            "help": AsyncMock(),
            "unknown-command": AsyncMock()
        })

        sender = u.User(UserID("@sender:example.org"))
        sender.command_status = {}

        result = await command_processor.handle(
            room_id=RoomID("#mock_room:example.org"),
            event_id=EventID("$H45H:example.org"),
            sender=sender,
            command="foo",
            args=[],
            is_management=boolean2[0],
            is_portal=boolean2[1],
        )

        assert result is None
        command_handlers = mautrix.bridge.commands.handler.command_handlers
        command_handlers["help"].mock.assert_not_called()  # type: ignore
        command_handlers["unknown-command"].mock.assert_called_once(
        )  # type: ignore

    @pytest.mark.asyncio
    async def test_handle_delegated_handler(
            self, command_processor: CommandProcessor,
            boolean2: Tuple[bool, bool], mocker: MockFixture) -> None:
        mocker.patch('mautrix_telegram.user.config', self.config)
        mocker.patch('mautrix.bridge.commands.handler.command_handlers', {
            "help": AsyncMock(),
            "unknown-command": AsyncMock()
        })

        sender = u.User(UserID("@sender:example.org"))
        sender.command_status = {"foo": AsyncMock(), "next": AsyncMock()}

        result = await command_processor.handle(
            room_id=RoomID("#mock_room:example.org"),
            event_id=EventID("$H45H:example.org"),
            sender=sender,  # u.User
            command="foo",
            args=[],
            is_management=boolean2[0],
            is_portal=boolean2[1])

        assert result is None
        command_handlers = mautrix.bridge.commands.handler.command_handlers
        command_handlers["help"].mock.assert_not_called()  # type: ignore
        command_handlers["unknown-command"].mock.assert_not_called(
        )  # type: ignore
        sender.command_status["foo"].mock.assert_not_called()  # type: ignore
        sender.command_status["next"].mock.assert_called_once()  # type: ignore
Example #5
0
class TestCommandHandler:
    config = Config("", "", "")
    config["bridge.permissions"] = {"*": "noperm"}

    @pytest.mark.parametrize(("needs_auth,"
                              "needs_puppeting,"
                              "needs_matrix_puppeting,"
                              "needs_admin,"
                              "management_only,"),
                             [l for l in list_true_once_each(length=5)])
    @pytest.mark.asyncio
    async def test_permissions_denied(
        self,
        needs_auth: bool,
        needs_puppeting: bool,
        needs_matrix_puppeting: bool,
        needs_admin: bool,
        management_only: bool,
        command_processor: CommandProcessor,
        boolean: bool,
        mocker: MockFixture,
    ) -> None:
        mocker.patch("mautrix_telegram.user.config", self.config)

        command = "testcmd"

        mock_handler = Mock()

        command_handler = CommandHandler(
            handler=mock_handler,
            needs_auth=needs_auth,
            needs_puppeting=needs_puppeting,
            needs_matrix_puppeting=needs_matrix_puppeting,
            needs_admin=needs_admin,
            management_only=management_only,
            name=command,
            help_text="No real command",
            help_args="mock mockmock",
            help_section=HelpSection("Mock Section", 42, ""),
        )

        sender = u.User(UserID("@sender:example.org"))
        sender.puppet_whitelisted = False
        sender.matrix_puppet_whitelisted = False
        sender.is_admin = False

        event = CommandEvent(
            processor=command_processor,
            room_id=RoomID("#mock_room:example.org"),
            event_id=EventID("$H45H:example.org"),
            sender=sender,
            command=command,
            args=[],
            is_management=False,
            is_portal=boolean,
        )

        assert await command_handler.get_permission_error(event)
        assert not command_handler.has_permission(
            HelpCacheKey(False, False, False, False, False, False))

    @pytest.mark.parametrize(("is_management,"
                              "puppet_whitelisted,"
                              "matrix_puppet_whitelisted,"
                              "is_admin,"
                              "is_logged_in,"),
                             [l for l in list_true_once_each(length=5)])
    @pytest.mark.asyncio
    async def test_permission_granted(
        self,
        is_management: bool,
        puppet_whitelisted: bool,
        matrix_puppet_whitelisted: bool,
        is_admin: bool,
        is_logged_in: bool,
        command_processor: CommandProcessor,
        boolean: bool,
        mocker: MockFixture,
    ) -> None:
        mocker.patch("mautrix_telegram.user.config", self.config)

        command = "testcmd"

        mock_handler = Mock()

        command_handler = CommandHandler(
            handler=mock_handler,
            needs_auth=False,
            needs_puppeting=False,
            needs_matrix_puppeting=False,
            needs_admin=False,
            management_only=False,
            name=command,
            help_text="No real command",
            help_args="mock mockmock",
            help_section=HelpSection("Mock Section", 42, ""),
        )

        sender = u.User(UserID("@sender:example.org"))
        sender.puppet_whitelisted = puppet_whitelisted
        sender.matrix_puppet_whitelisted = matrix_puppet_whitelisted
        sender.is_admin = is_admin
        mocker.patch.object(u.User, 'is_logged_in', return_value=is_logged_in)

        event = CommandEvent(
            processor=command_processor,
            room_id=RoomID("#mock_room:example.org"),
            event_id=EventID("$H45H:example.org"),
            sender=sender,
            command=command,
            args=[],
            is_management=is_management,
            is_portal=boolean,
        )

        assert not await command_handler.get_permission_error(event)
        assert command_handler.has_permission(
            HelpCacheKey(is_management=is_management,
                         puppet_whitelisted=puppet_whitelisted,
                         matrix_puppet_whitelisted=matrix_puppet_whitelisted,
                         is_admin=is_admin,
                         is_logged_in=is_logged_in,
                         is_portal=boolean))
Example #6
0
from os.path import abspath, dirname

sys.path.insert(0, dirname(dirname(abspath(__file__))))

from mautrix.util.db import Base
import mautrix_telegram.db
from mautrix_telegram.config import Config
from alchemysession import AlchemySessionContainer

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

mxtg_config_path = context.get_x_argument(as_dictionary=True).get(
    "config", "config.yaml")
mxtg_config = Config(mxtg_config_path, None, None)
mxtg_config.load()
config.set_main_option("sqlalchemy.url",
                       mxtg_config["appservice.database"].replace("%", "%%"))

AlchemySessionContainer.create_table_classes(None, "telethon_", Base)

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = Base.metadata
Example #7
0
import sys
from os.path import abspath, dirname

sys.path.insert(0, dirname(dirname(abspath(__file__))))

from mautrix_telegram.base import Base
from mautrix_telegram.config import Config
from alchemysession import AlchemySessionContainer
import mautrix_telegram.db

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

mxtg_config_path = context.get_x_argument(as_dictionary=True).get("config", "config.yaml")
mxtg_config = Config(mxtg_config_path, None, None)
mxtg_config.load()
config.set_main_option("sqlalchemy.url",
                       mxtg_config.get("appservice.database", "sqlite:///mautrix-telegram.db"))


class FakeDB:
    @staticmethod
    def query_property():
        return None


AlchemySessionContainer.create_table_classes(FakeDB(), "telethon_", Base)

# Interpret the config file for Python logging.
# This line sets up loggers basically.
Example #8
0
from mautrix_telegram.config import Config
from mautrix_telegram.db import Portal, Message, Puppet, BotChat
from .models import ChatLink, TgUser, MatrixUser, Message as TMMessage, Base as TelematrixBase

parser = argparse.ArgumentParser(
    description="mautrix-telegram telematrix import script",
    prog="python -m mautrix_telegram.scripts.telematrix_import")
parser.add_argument("-c", "--config", type=str, default="config.yaml",
                    metavar="<path>", help="the path to your mautrix-telegram config file")
parser.add_argument("-b", "--bot-id", type=int, required=True,
                    metavar="<id>", help="the telegram user ID of your relay bot")
parser.add_argument("-t", "--telematrix-database", type=str, default="sqlite:///database.db",
                    metavar="<url>", help="your telematrix database URL")
args = parser.parse_args()

config = Config(args.config, None, None)
config.load()

mxtg_db_engine = sql.create_engine(config.get("appservice.database", "sqlite:///mautrix-telegram.db"))
mxtg = orm.sessionmaker(bind=mxtg_db_engine)()
Base.metadata.bind = mxtg_db_engine

telematrix_db_engine = sql.create_engine(args.telematrix_database)
telematrix = orm.sessionmaker(bind=telematrix_db_engine)()
TelematrixBase.metadata.bind = telematrix_db_engine

chat_links = telematrix.query(ChatLink).all()
tg_users = telematrix.query(TgUser).all()
mx_users = telematrix.query(MatrixUser).all()
messages = telematrix.query(TMMessage).all()
Example #9
0
from mautrix_telegram.config import Config

from .models import ChatLink, TgUser, MatrixUser, Message as TMMessage, Base as TelematrixBase

parser = argparse.ArgumentParser(
    description="mautrix-telegram telematrix import script",
    prog="python -m mautrix_telegram.scripts.telematrix_import")
parser.add_argument("-c", "--config", type=str, default="config.yaml",
                    metavar="<path>", help="the path to your mautrix-telegram config file")
parser.add_argument("-b", "--bot-id", type=int, required=True,
                    metavar="<id>", help="the telegram user ID of your relay bot")
parser.add_argument("-t", "--telematrix-database", type=str, default="sqlite:///database.db",
                    metavar="<url>", help="your telematrix database URL")
args = parser.parse_args()

config = Config(args.config, None, None)
config.load()

mxtg_db_engine = sql.create_engine(
    config.get("appservice.database", "sqlite:///mautrix-telegram.db"))
mxtg = orm.sessionmaker(bind=mxtg_db_engine)()
Base.metadata.bind = mxtg_db_engine

telematrix_db_engine = sql.create_engine(args.telematrix_database)
telematrix = orm.sessionmaker(bind=telematrix_db_engine)()
TelematrixBase.metadata.bind = telematrix_db_engine

chat_links = telematrix.query(ChatLink).all()
tg_users = telematrix.query(TgUser).all()
mx_users = telematrix.query(MatrixUser).all()
tm_messages = telematrix.query(TMMessage).all()
Example #10
0
                    help="the path to your mautrix-telegram config file")
parser.add_argument("-b",
                    "--bot-id",
                    type=int,
                    required=True,
                    metavar="<id>",
                    help="the telegram user ID of your relay bot")
parser.add_argument("-t",
                    "--telematrix-database",
                    type=str,
                    default="sqlite:///database.db",
                    metavar="<url>",
                    help="your telematrix database URL")
args = parser.parse_args()

config = Config(args.config, None, None)
config.load()

mxtg_db_engine = sql.create_engine(config["appservice.database"])
mxtg = orm.sessionmaker(bind=mxtg_db_engine)()
Base.metadata.bind = mxtg_db_engine

telematrix_db_engine = sql.create_engine(args.telematrix_database)
telematrix = orm.sessionmaker(bind=telematrix_db_engine)()
TelematrixBase.metadata.bind = telematrix_db_engine

chat_links = telematrix.query(ChatLink).all()
tg_users = telematrix.query(TgUser).all()
mx_users = telematrix.query(MatrixUser).all()
tm_messages = telematrix.query(TMMessage).all()