nixpkgs/nixos/tests/matrix/appservice-irc.nix
Silvan Mosberger 4f0dadbf38 treewide: format all inactive Nix files
After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build a08b3a4d19.tar.gz \
      --argstr baseRev b32a094368
    result/bin/apply-formatting $NIXPKGS_PATH
2024-12-10 20:26:33 +01:00

244 lines
7.4 KiB
Nix

{ pkgs, ... }:
let
homeserverUrl = "http://homeserver:8008";
in
{
name = "matrix-appservice-irc";
meta = {
maintainers = pkgs.matrix-appservice-irc.meta.maintainers;
};
nodes = {
homeserver = {
# 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 = {
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";
};
};
mediaProxy = {
publicUrl = "http://localhost:11111/media";
ttl = 0;
};
};
};
};
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)
appservice.wait_for_file("/var/lib/matrix-appservice-irc/media-signingkey.jwk")
appservice.wait_for_open_port(11111)
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")
'';
}