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