From 855c95817188cf9cc4ba4d916399c192c8788df9 Mon Sep 17 00:00:00 2001 From: eymeric Date: Wed, 5 Aug 2026 16:06:11 +0700 Subject: [PATCH 1/4] mautrix-meta: add mautrix-instagram binary build --- pkgs/by-name/ma/mautrix-meta/package.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/by-name/ma/mautrix-meta/package.nix b/pkgs/by-name/ma/mautrix-meta/package.nix index 81703b68f81f..3ca0d7d53454 100644 --- a/pkgs/by-name/ma/mautrix-meta/package.nix +++ b/pkgs/by-name/ma/mautrix-meta/package.nix @@ -18,7 +18,10 @@ buildGoModule rec { version = "26.07"; tag = "v0.2607.0"; - subPackages = [ "cmd/mautrix-meta" ]; + subPackages = [ + "cmd/mautrix-meta" + "cmd/mautrix-instagram" + ]; src = fetchFromGitHub { owner = "mautrix"; From 0ca90c55e00641b0d95eee609df8de48c87dd80e Mon Sep 17 00:00:00 2001 From: eymeric Date: Wed, 5 Aug 2026 16:06:35 +0700 Subject: [PATCH 2/4] nixos/mautrix-meta: automatically select the right binary based on mode instagram or others --- nixos/modules/services/matrix/mautrix-meta.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nixos/modules/services/matrix/mautrix-meta.nix b/nixos/modules/services/matrix/mautrix-meta.nix index a0576c79edb3..1645ef3cdc8a 100644 --- a/nixos/modules/services/matrix/mautrix-meta.nix +++ b/nixos/modules/services/matrix/mautrix-meta.nix @@ -18,6 +18,7 @@ let settingsFileUnsubstituted = cfg: settingsFormat.generate "mautrix-meta-config.yaml" cfg.settings; metaName = name: "mautrix-meta-${name}"; + packageName = network: if network == "instagram" then "mautrix-instagram" else "mautrix-meta"; enabledInstances = lib.filterAttrs ( name: config: config.enable @@ -471,7 +472,7 @@ in cp '${settingsFile cfg}' '${settingsFile cfg}.tmp' echo "Generating registration file" - mautrix-meta \ + ${lib.getExe' upperCfg.package (packageName cfg.settings.network.mode)} \ --generate-registration \ --config='${settingsFile cfg}.tmp' \ --registration='${cfg.registrationFile}' @@ -568,7 +569,7 @@ in EnvironmentFile = cfg.environmentFile; ExecStart = lib.escapeShellArgs [ - (lib.getExe upperCfg.package) + (lib.getExe' upperCfg.package (packageName cfg.settings.network.mode)) "--config=${settingsFile cfg}" ]; }; From a6a86e4929a19fdf6d8b449607b2b446f740edae Mon Sep 17 00:00:00 2001 From: eymeric Date: Fri, 7 Aug 2026 08:26:25 +0700 Subject: [PATCH 3/4] nixos/mautrix-meta: update settings description example generation method --- nixos/modules/services/matrix/mautrix-meta.nix | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nixos/modules/services/matrix/mautrix-meta.nix b/nixos/modules/services/matrix/mautrix-meta.nix index 1645ef3cdc8a..9fbd58b18d2a 100644 --- a/nixos/modules/services/matrix/mautrix-meta.nix +++ b/nixos/modules/services/matrix/mautrix-meta.nix @@ -201,8 +201,10 @@ in ''; description = '' {file}`config.yaml` configuration as a Nix attribute set. - Configuration options should match those described in - [example-config.yaml](https://github.com/mautrix/meta/blob/main/example-config.yaml). + Configuration options should match those described in the example configuration. + Get an example configuration by executing one of those commands + - `mautrix-meta -c example.yaml --generate-example-config` + - `mautrix-instagram -c example.yaml --generate-example-config` Secret tokens should be specified using {option}`environmentFile` instead From 61c0c7acdb6a43eaa0d8bd77429f38a768e7a5b4 Mon Sep 17 00:00:00 2001 From: eymeric Date: Thu, 6 Aug 2026 09:45:27 +0700 Subject: [PATCH 4/4] nixos/tests/matrix/mautrix-meta: fix tests for newer mautrix versions Co-authored-by: Gemini CLI --- nixos/tests/matrix/mautrix-meta-postgres.nix | 35 ++++++++----- nixos/tests/matrix/mautrix-meta-sqlite.nix | 54 +++++++++++++------- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/nixos/tests/matrix/mautrix-meta-postgres.nix b/nixos/tests/matrix/mautrix-meta-postgres.nix index b1ecf5da3cdd..bf28b889ecec 100644 --- a/nixos/tests/matrix/mautrix-meta-postgres.nix +++ b/nixos/tests/matrix/mautrix-meta-postgres.nix @@ -90,12 +90,21 @@ in as_token = "$AS_TOKEN"; hs_token = "$HS_TOKEN"; - database = { - type = "postgres"; - uri = "postgres:///mautrix-meta-instagram?host=/var/run/postgresql"; + bot = { + username = botUserName; + avatar = ""; }; + }; - bot.username = botUserName; + database = { + type = "postgres"; + uri = "postgres:///mautrix-meta-instagram?host=/var/run/postgresql"; + }; + + encryption = { + allow = false; + default = false; + require = false; }; bridge.permissions."@${userName}:server" = "user"; @@ -127,13 +136,14 @@ in import functools import asyncio - from nio import AsyncClient, RoomMessageNotice, RoomCreateResponse, RoomInviteResponse + from nio import AsyncClient, RoomMessageText, RoomCreateResponse, RoomInviteResponse - async def message_callback(matrix: AsyncClient, msg: str, _r, e): + async def message_callback(matrix: AsyncClient, expected_msg: str, expected_sender: str, _r, e): print("Received matrix text message: ", e) - assert msg in e.body - exit(0) # Success! + if getattr(e, "sender", "") == expected_sender and expected_msg in getattr(e, "body", ""): + print("Success!") + exit(0) # Success! async def run(homeserver: str): @@ -151,9 +161,9 @@ in assert isinstance(response, RoomInviteResponse) callback = functools.partial( - message_callback, matrix, "Hello, I'm an Instagram bridge bot." + message_callback, matrix, "Hello, I'm a Instagram bridge bot.", "@${botUserName}:${homeserverDomain}" ) - matrix.add_event_callback(callback, RoomMessageNotice) + matrix.add_event_callback(callback, RoomMessageText) print("Waiting for matrix message...") await matrix.sync_forever(timeout=30000) @@ -171,11 +181,10 @@ in def extract_token(data): stdout = data[1] stdout = stdout.strip() - line = stdout.split('\n')[-1] - return line.split(':')[-1].strip("\" '\n") + return stdout.split(':')[-1].strip("\" '\n") def get_token_from(token, file): - data = server.execute(f"cat {file} | grep {token}") + data = server.execute(f"grep -E '^\\s*{token}:' {file}") return extract_token(data) def get_as_token_from(file): diff --git a/nixos/tests/matrix/mautrix-meta-sqlite.nix b/nixos/tests/matrix/mautrix-meta-sqlite.nix index d4692dec718e..085910eeb19b 100644 --- a/nixos/tests/matrix/mautrix-meta-sqlite.nix +++ b/nixos/tests/matrix/mautrix-meta-sqlite.nix @@ -4,7 +4,7 @@ let homeserverUrl = "http://server:8008"; username = "alice"; instagramBotUsername = "instagrambot"; - facebookBotUsername = "facebookbot"; + metaBotUsername = "metabot"; in { name = "mautrix-meta-sqlite"; @@ -60,7 +60,16 @@ in appservice = { port = 8009; - bot.username = facebookBotUsername; + bot = { + username = metaBotUsername; + avatar = ""; + }; + }; + + encryption = { + allow = false; + default = false; + require = false; }; bridge.permissions."@${username}:server" = "user"; @@ -79,7 +88,16 @@ in appservice = { port = 8010; - bot.username = instagramBotUsername; + bot = { + username = instagramBotUsername; + avatar = ""; + }; + }; + + encryption = { + allow = false; + default = false; + require = false; }; bridge.permissions."@${username}:server" = "user"; @@ -136,16 +154,17 @@ in import functools import asyncio - from nio import AsyncClient, RoomMessageNotice, RoomCreateResponse, RoomInviteResponse + from nio import AsyncClient, RoomMessageText, RoomCreateResponse, RoomInviteResponse - async def message_callback(matrix: AsyncClient, msg: str, _r, e): + async def message_callback(matrix: AsyncClient, expected_msg: str, expected_sender: str, _r, e): print("Received matrix text message: ", e) - assert msg in e.body - exit(0) # Success! + if getattr(e, "sender", "") == expected_sender and expected_msg in getattr(e, "body", ""): + print("Success!") + exit(0) # Success! - async def run(username: str, bot_username: str, homeserver: str): + async def run(username: str, bot_username: str, homeserver: str, expected_msg: str): matrix = AsyncClient(homeserver, f"@{username}:${homeserverDomain}") response = await matrix.login("foobar") @@ -161,16 +180,16 @@ in assert isinstance(response, RoomInviteResponse) callback = functools.partial( - message_callback, matrix, "Hello, I'm an Instagram bridge bot." + message_callback, matrix, expected_msg, f"@{bot_username}:${homeserverDomain}" ) - matrix.add_event_callback(callback, RoomMessageNotice) + matrix.add_event_callback(callback, RoomMessageText) print("Waiting for matrix message...") await matrix.sync_forever(timeout=30000) if __name__ == "__main__": - asyncio.run(run(sys.argv[1], sys.argv[2], sys.argv[3])) + asyncio.run(run(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])) '' ) ]; @@ -181,11 +200,10 @@ in def extract_token(data): stdout = data[1] stdout = stdout.strip() - line = stdout.split('\n')[-1] - return line.split(':')[-1].strip("\" '\n") + return stdout.split(':')[-1].strip("\" '\n") def get_token_from(token, file): - data = server.execute(f"cat {file} | grep {token}") + data = server.execute(f"grep -E '^\\s*{token}:' {file}") return extract_token(data) def get_as_token_from(file): @@ -216,8 +234,8 @@ in client.succeed("register_user ${username} ${homeserverUrl} >&2") with subtest("ensure messages can be exchanged"): - client.succeed("do_test ${username} ${facebookBotUsername} ${homeserverUrl} >&2") - client.succeed("do_test ${username} ${instagramBotUsername} ${homeserverUrl} >&2") + client.succeed("do_test ${username} ${metaBotUsername} ${homeserverUrl} \"Hello, I'm a Facebook Messenger bridge bot.\" >&2") + client.succeed("do_test ${username} ${instagramBotUsername} ${homeserverUrl} \"Hello, I'm a Instagram bridge bot.\" >&2") with subtest("ensure as_token and hs_token stays same after restart"): generated_as_token_facebook = get_as_token_from(config_yaml) @@ -252,7 +270,7 @@ in assert generated_hs_token_facebook == new_hs_token_facebook, f"hs_token should stay the same after restart inside the registration file (is: {new_hs_token_facebook}, was: {generated_hs_token_facebook})" with subtest("ensure messages can be exchanged after restart"): - client.succeed("do_test ${username} ${instagramBotUsername} ${homeserverUrl} >&2") - client.succeed("do_test ${username} ${facebookBotUsername} ${homeserverUrl} >&2") + client.succeed("do_test ${username} ${instagramBotUsername} ${homeserverUrl} \"Hello, I'm a Instagram bridge bot.\" >&2") + client.succeed("do_test ${username} ${metaBotUsername} ${homeserverUrl} \"Hello, I'm a Facebook Messenger bridge bot.\" >&2") ''; }