at 24.11-pre 8.0 kB view raw
1import ../make-test-python.nix ({ pkgs, ... }: 2 let 3 homeserverDomain = "server"; 4 homeserverUrl = "http://server:8008"; 5 userName = "alice"; 6 botUserName = "instagrambot"; 7 8 asToken = "this-is-my-totally-randomly-generated-as-token"; 9 hsToken = "this-is-my-totally-randomly-generated-hs-token"; 10 in 11 { 12 name = "mautrix-meta-postgres"; 13 meta.maintainers = pkgs.mautrix-meta.meta.maintainers; 14 15 nodes = { 16 server = { config, pkgs, ... }: { 17 services.postgresql = { 18 enable = true; 19 20 ensureUsers = [ 21 { 22 name = "mautrix-meta-instagram"; 23 ensureDBOwnership = true; 24 } 25 ]; 26 27 ensureDatabases = [ 28 "mautrix-meta-instagram" 29 ]; 30 }; 31 32 systemd.services.mautrix-meta-instagram = { 33 wants = [ "postgres.service" ]; 34 after = [ "postgres.service" ]; 35 }; 36 37 services.matrix-synapse = { 38 enable = true; 39 settings = { 40 database.name = "sqlite3"; 41 42 enable_registration = true; 43 44 # don't use this in production, always use some form of verification 45 enable_registration_without_verification = true; 46 47 listeners = [ { 48 # The default but tls=false 49 bind_addresses = [ 50 "0.0.0.0" 51 ]; 52 port = 8008; 53 resources = [ { 54 "compress" = true; 55 "names" = [ "client" ]; 56 } { 57 "compress" = false; 58 "names" = [ "federation" ]; 59 } ]; 60 tls = false; 61 type = "http"; 62 } ]; 63 }; 64 }; 65 66 services.mautrix-meta.instances.instagram = { 67 enable = true; 68 69 environmentFile = pkgs.writeText ''my-secrets'' '' 70 AS_TOKEN=${asToken} 71 HS_TOKEN=${hsToken} 72 ''; 73 74 settings = { 75 homeserver = { 76 address = homeserverUrl; 77 domain = homeserverDomain; 78 }; 79 80 appservice = { 81 port = 8009; 82 83 as_token = "$AS_TOKEN"; 84 hs_token = "$HS_TOKEN"; 85 86 database = { 87 type = "postgres"; 88 uri = "postgres:///mautrix-meta-instagram?host=/var/run/postgresql"; 89 }; 90 91 bot.username = botUserName; 92 }; 93 94 bridge.permissions."@${userName}:server" = "user"; 95 }; 96 }; 97 98 networking.firewall.allowedTCPPorts = [ 8008 8009 ]; 99 }; 100 101 client = { pkgs, ... }: { 102 environment.systemPackages = [ 103 (pkgs.writers.writePython3Bin "do_test" 104 { 105 libraries = [ pkgs.python3Packages.matrix-nio ]; 106 flakeIgnore = [ 107 # We don't live in the dark ages anymore. 108 # Languages like Python that are whitespace heavy will overrun 109 # 79 characters.. 110 "E501" 111 ]; 112 } '' 113 import sys 114 import functools 115 import asyncio 116 117 from nio import AsyncClient, RoomMessageNotice, RoomCreateResponse, RoomInviteResponse 118 119 120 async def message_callback(matrix: AsyncClient, msg: str, _r, e): 121 print("Received matrix text message: ", e) 122 assert msg in e.body 123 exit(0) # Success! 124 125 126 async def run(homeserver: str): 127 matrix = AsyncClient(homeserver) 128 response = await matrix.register("${userName}", "foobar") 129 print("Matrix register response: ", response) 130 131 # Open a DM with the bridge bot 132 response = await matrix.room_create() 133 print("Matrix create room response:", response) 134 assert isinstance(response, RoomCreateResponse) 135 room_id = response.room_id 136 137 response = await matrix.room_invite(room_id, "@${botUserName}:${homeserverDomain}") 138 assert isinstance(response, RoomInviteResponse) 139 140 callback = functools.partial( 141 message_callback, matrix, "Hello, I'm an Instagram bridge bot." 142 ) 143 matrix.add_event_callback(callback, RoomMessageNotice) 144 145 print("Waiting for matrix message...") 146 await matrix.sync_forever(timeout=30000) 147 148 149 if __name__ == "__main__": 150 asyncio.run(run(sys.argv[1])) 151 '' 152 ) 153 ]; 154 }; 155 }; 156 157 testScript = '' 158 def extract_token(data): 159 stdout = data[1] 160 stdout = stdout.strip() 161 line = stdout.split('\n')[-1] 162 return line.split(':')[-1].strip("\" '\n") 163 164 def get_token_from(token, file): 165 data = server.execute(f"cat {file} | grep {token}") 166 return extract_token(data) 167 168 def get_as_token_from(file): 169 return get_token_from("as_token", file) 170 171 def get_hs_token_from(file): 172 return get_token_from("hs_token", file) 173 174 config_yaml = "/var/lib/mautrix-meta-instagram/config.yaml" 175 registration_yaml = "/var/lib/mautrix-meta-instagram/meta-registration.yaml" 176 177 expected_as_token = "${asToken}" 178 expected_hs_token = "${hsToken}" 179 180 start_all() 181 182 with subtest("start the server"): 183 # bridge 184 server.wait_for_unit("mautrix-meta-instagram.service") 185 186 # homeserver 187 server.wait_for_unit("matrix-synapse.service") 188 189 server.wait_for_open_port(8008) 190 # Bridge only opens the port after it contacts the homeserver 191 server.wait_for_open_port(8009) 192 193 with subtest("ensure messages can be exchanged"): 194 client.succeed("do_test ${homeserverUrl} >&2") 195 196 with subtest("ensure as_token, hs_token match from environment file"): 197 as_token = get_as_token_from(config_yaml) 198 hs_token = get_hs_token_from(config_yaml) 199 as_token_registration = get_as_token_from(registration_yaml) 200 hs_token_registration = get_hs_token_from(registration_yaml) 201 202 assert as_token == expected_as_token, f"as_token in config should match the one specified (is: {as_token}, expected: {expected_as_token})" 203 assert hs_token == expected_hs_token, f"hs_token in config should match the one specified (is: {hs_token}, expected: {expected_hs_token})" 204 assert as_token_registration == expected_as_token, f"as_token in registration should match the one specified (is: {as_token_registration}, expected: {expected_as_token})" 205 assert hs_token_registration == expected_hs_token, f"hs_token in registration should match the one specified (is: {hs_token_registration}, expected: {expected_hs_token})" 206 207 with subtest("ensure as_token and hs_token stays same after restart"): 208 server.systemctl("restart mautrix-meta-instagram") 209 server.wait_for_open_port(8009) 210 211 as_token = get_as_token_from(config_yaml) 212 hs_token = get_hs_token_from(config_yaml) 213 as_token_registration = get_as_token_from(registration_yaml) 214 hs_token_registration = get_hs_token_from(registration_yaml) 215 216 assert as_token == expected_as_token, f"as_token in config should match the one specified (is: {as_token}, expected: {expected_as_token})" 217 assert hs_token == expected_hs_token, f"hs_token in config should match the one specified (is: {hs_token}, expected: {expected_hs_token})" 218 assert as_token_registration == expected_as_token, f"as_token in registration should match the one specified (is: {as_token_registration}, expected: {expected_as_token})" 219 assert hs_token_registration == expected_hs_token, f"hs_token in registration should match the one specified (is: {hs_token_registration}, expected: {expected_hs_token})" 220 ''; 221 })