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