226 lines
7.1 KiB
Nix
226 lines
7.1 KiB
Nix
import ../make-test-python.nix ({ pkgs, ... }:
|
|
let
|
|
homeserverUrl = "http://homeserver:8008";
|
|
in
|
|
{
|
|
name = "matrix-appservice-irc";
|
|
meta = {
|
|
maintainers = pkgs.matrix-appservice-irc.meta.maintainers;
|
|
};
|
|
|
|
nodes = {
|
|
homeserver = { pkgs, ... }: {
|
|
# We'll switch to this once the config is copied into place
|
|
specialisation.running.configuration = {
|
|
services.matrix-synapse = {
|
|
enable = true;
|
|
settings = {
|
|
database.name = "sqlite3";
|
|
app_service_config_files = [ "/registration.yml" ];
|
|
|
|
enable_registration = true;
|
|
|
|
# don't use this in production, always use some form of verification
|
|
enable_registration_without_verification = true;
|
|
|
|
listeners = [ {
|
|
# The default but tls=false
|
|
bind_addresses = [
|
|
"0.0.0.0"
|
|
];
|
|
port = 8008;
|
|
resources = [ {
|
|
"compress" = true;
|
|
"names" = [ "client" ];
|
|
} {
|
|
"compress" = false;
|
|
"names" = [ "federation" ];
|
|
} ];
|
|
tls = false;
|
|
type = "http";
|
|
} ];
|
|
};
|
|
};
|
|
|
|
networking.firewall.allowedTCPPorts = [ 8008 ];
|
|
};
|
|
};
|
|
|
|
ircd = { pkgs, ... }: {
|
|
services.ngircd = {
|
|
enable = true;
|
|
config = ''
|
|
[Global]
|
|
Name = ircd.ircd
|
|
Info = Server Info Text
|
|
AdminInfo1 = _
|
|
|
|
[Channel]
|
|
Name = #test
|
|
Topic = a cool place
|
|
|
|
[Options]
|
|
PAM = no
|
|
'';
|
|
};
|
|
networking.firewall.allowedTCPPorts = [ 6667 ];
|
|
};
|
|
|
|
appservice = { pkgs, ... }: {
|
|
services.matrix-appservice-irc = {
|
|
enable = true;
|
|
registrationUrl = "http://appservice:8009";
|
|
|
|
settings = {
|
|
homeserver.url = homeserverUrl;
|
|
homeserver.domain = "homeserver";
|
|
|
|
ircService.servers."ircd" = {
|
|
name = "IRCd";
|
|
port = 6667;
|
|
dynamicChannels = {
|
|
enabled = true;
|
|
aliasTemplate = "#irc_$CHANNEL";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
networking.firewall.allowedTCPPorts = [ 8009 ];
|
|
};
|
|
|
|
client = { pkgs, ... }: {
|
|
environment.systemPackages = [
|
|
(pkgs.writers.writePython3Bin "do_test"
|
|
{
|
|
libraries = [ pkgs.python3Packages.matrix-nio ];
|
|
flakeIgnore = [
|
|
# We don't live in the dark ages anymore.
|
|
# Languages like Python that are whitespace heavy will overrun
|
|
# 79 characters..
|
|
"E501"
|
|
];
|
|
} ''
|
|
import sys
|
|
import socket
|
|
import functools
|
|
from time import sleep
|
|
import asyncio
|
|
|
|
from nio import AsyncClient, RoomMessageText, JoinResponse
|
|
|
|
|
|
async def matrix_room_message_text_callback(matrix: AsyncClient, msg: str, _r, e):
|
|
print("Received matrix text message: ", e)
|
|
if msg in e.body:
|
|
print("Received hi from IRC")
|
|
await matrix.close()
|
|
exit(0) # Actual exit point
|
|
|
|
|
|
class IRC:
|
|
def __init__(self):
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
sock.connect(("ircd", 6667))
|
|
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
|
sock.send(b"USER bob bob bob :bob\n")
|
|
sock.send(b"NICK bob\n")
|
|
self.sock = sock
|
|
|
|
def join(self, room: str):
|
|
self.sock.send(f"JOIN {room}\n".encode())
|
|
|
|
def privmsg(self, room: str, msg: str):
|
|
self.sock.send(f"PRIVMSG {room} :{msg}\n".encode())
|
|
|
|
def expect_msg(self, body: str):
|
|
buffer = ""
|
|
while True:
|
|
buf = self.sock.recv(1024).decode()
|
|
buffer += buf
|
|
if body in buffer:
|
|
return
|
|
|
|
|
|
async def run(homeserver: str):
|
|
irc = IRC()
|
|
|
|
matrix = AsyncClient(homeserver)
|
|
response = await matrix.register("alice", "foobar")
|
|
print("Matrix register response: ", response)
|
|
|
|
response = await matrix.join("#irc_#test:homeserver")
|
|
print("Matrix join room response:", response)
|
|
assert isinstance(response, JoinResponse)
|
|
room_id = response.room_id
|
|
|
|
irc.join("#test")
|
|
# FIXME: what are we waiting on here? Matrix? IRC? Both?
|
|
# 10s seem bad for busy hydra machines.
|
|
sleep(10)
|
|
|
|
# Exchange messages
|
|
print("Sending text message to matrix room")
|
|
response = await matrix.room_send(
|
|
room_id=room_id,
|
|
message_type="m.room.message",
|
|
content={"msgtype": "m.text", "body": "hi from matrix"},
|
|
)
|
|
print("Matrix room send response: ", response)
|
|
irc.privmsg("#test", "hi from irc")
|
|
|
|
print("Waiting for the matrix message to appear on the IRC side...")
|
|
irc.expect_msg("hi from matrix")
|
|
|
|
callback = functools.partial(
|
|
matrix_room_message_text_callback, matrix, "hi from irc"
|
|
)
|
|
matrix.add_event_callback(callback, RoomMessageText)
|
|
|
|
print("Waiting for matrix message...")
|
|
await matrix.sync_forever()
|
|
|
|
exit(1) # Unreachable
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(run(sys.argv[1]))
|
|
''
|
|
)
|
|
];
|
|
};
|
|
};
|
|
|
|
testScript = ''
|
|
import pathlib
|
|
import os
|
|
|
|
start_all()
|
|
|
|
ircd.wait_for_unit("ngircd.service")
|
|
ircd.wait_for_open_port(6667)
|
|
|
|
with subtest("start the appservice"):
|
|
appservice.wait_for_unit("matrix-appservice-irc.service")
|
|
appservice.wait_for_open_port(8009)
|
|
|
|
with subtest("copy the registration file"):
|
|
appservice.copy_from_vm("/var/lib/matrix-appservice-irc/registration.yml")
|
|
homeserver.copy_from_host(
|
|
str(pathlib.Path(os.environ.get("out", os.getcwd())) / "registration.yml"), "/"
|
|
)
|
|
homeserver.succeed("chmod 444 /registration.yml")
|
|
|
|
with subtest("start the homeserver"):
|
|
homeserver.succeed(
|
|
"/run/current-system/specialisation/running/bin/switch-to-configuration test >&2"
|
|
)
|
|
|
|
homeserver.wait_for_unit("matrix-synapse.service")
|
|
homeserver.wait_for_open_port(8008)
|
|
|
|
with subtest("ensure messages can be exchanged"):
|
|
client.succeed("do_test ${homeserverUrl} >&2")
|
|
'';
|
|
})
|