~funderscore blog cgit wiki get in touch
aboutsummaryrefslogtreecommitdiff

Matterpuppeter

An API plugin for Matterbridge, that creates IRC puppets

Features

Turns this:

<Someone> rPerson, rando: hi both
<Matterbridge> [j] <rPerson> hello
<Matterbridge> [mx] <rando> Hi!
<Matterbridge> [irc2] <user> can i join in?

into this:

<Someone> rPerson|j, rando|mx: hi both
<rPerson|j> hello
--> rando|mx (934782619@matterpuppeter) (@rando:matrix.org [matrix.mxo]) has joined #chat
<rando|mx> Hi!
<user|irc2> can i join in?
  • Lazy puppeting: creates a puppet only when users join or talk
  • Client limit: limits how many puppets can connect at the same time
  • Built-in configurable pastebinning of long codeblocks
  • Works with Matterbridge's REST API
  • Limited quit/join flood: keeps connections alive during a Matterbridge restart
  • Puppets are marked as "away" until Matterpuppeter can reconnect to the Matterbridge API

In other words:

     Any protocol supported 
        by Matterbridge
  (e.g. XMPP, Discord, Matrix)
               |
               |
               v
          Matterbridge
               |
               |      Matterbridge API
               v
         Matterpuppeter
               |
               |      IRC protocol
               v
          IRC network
   (e.g. OFTC, Libera.Chat)
               |
               |
               v
          IRC channel
        (e.g. ##coffee)

This is not a standalone bridge.

Caveats

  • Lazy puppeting: while this makes client counts lower, it still means people who do not have a puppet can still watch the channel on the other side, without users on IRC knowing.
  • Portalling-style bridging is not supported, on-purpose
  • Cannot bridge bans: matterbridge does not support bridging bans and kicks
  • Private messages are not supported
  • Connecting to multiple networks is not supported - run Matterpuppeter multiple times for each network instead

How to

This currently requires a fork of Matterbridge: https://git.vitali64.duckdns.org/misc/matterbridge.git

Create a Matterbridge config by following this guide.

Add the following at the top of your matterbridge.toml:

[api.matterpuppeter]
NoSendJoinPart=false
ShowJoinPart=true
BindAddress="127.0.0.1:4242"
Buffer=1000
RemoteNickFormat="{NICK}-{LABEL}"
Label="IRC"

If you're bridging to multiple IRC networks and want to use Matterpuppeter on all of them, you'll need one Matterpuppeter instance per network.

Add the following to one of the gateways you have configured:

[[gateway]]
name="gateway1"
<...>

    [[gateway.inout]]
    account="api.matterpuppeter"
    channel="api"

<...>

Now, you can configure Matterpuppeter itself. The configuration is in config.yaml, and is extensively documented. Do make sure to customise it, so it fits your bridging setup.

Here is a simple config file that will bridge to a ##Meow channel on Libera.Chat:

irc:
  host: "irc.libera.chat"
  port: 6697
  tls: true
  nick: "_Bridger"
  gecos: "Matterpuppeter listener bot"
  message_limit: 380
  client_limit: 6

  sasl:
    enable: false

paste:
  enable: false

ident:
  enable: false

api:
  host: "http://localhost:4242"
  account: "api.matterpuppeter"

gateway:
  "gateway1": "##Meow"

Pastebinning support

Long code blocks can be pastebinned to avoid spamming IRC. This can be useful when it is common practise to paste snippets of code which would cause spam on the IRC side. For example, the following message:

<f_> Here's my code:

     |  #include <stdio.h>
     |
     |  int main(int argc, char **argv)
     |  {
     |      print("This is a message\n");
     |
     |      return 0;
     |  }

can be bridged as:

<f_-X> Here's my code:
<f_-X> https://pastebin.matterpuppeter/<paste id here>

To configure this behaviour, first create a directory where Matterpuppeter will write code snippets to:

$ mkdir ~/pastes

Then, let an HTTP server serve files from that directory. For example, when using nginx:

server {
    server_name paste.matterpuppeter;
    listen 80;
    root /home/_mp/pastes;

    location / {
        index index.html;
    }
}

This is a very minimal configuration, which may not be suitable in production, but it gives an overall idea of how things should be set up. Also make sure that the pastes directory is readable by the user nginx runs as (typically www-data).

Finally, you can configure Matterpuppeter to make use of that directory:

paste:
  enable: true
  domain: "http://paste.matterpuppeter/"
  dir: "/home/_mp/pastes"
  maxlines: 5

Restart your HTTP server and Matterpuppeter, long code blocks should now be pastebinned! You will need to set up cleaning up yourself at this point however, but this is left as an exercise to the reader.

Identd

Matterpuppeter can integrate with an ident daemon for the purposes of identifying puppets. It does this by writing to an ident file, which would then be read by your system's ident server (such as oidentd) and sent to the IRC server. After this is done Matterpuppeter clears the contents of the file.

To do this, your /etc/oidentd.conf file must allow the user Matterpuppeter runs as to spoof ident queries:

user "_mp" {
    default {
        allow spoof
        allow spoof_all
    }
}

Then create an .oidentd.conf file in the home directory of the Matterpuppeter user while logged in as that user, and make sure oidentd can read it:

$ touch ~/.oidentd.conf
$ chmod 644 ~/.oidentd.conf
$ chmod 711 ~

Finally, configure Matterpuppeter to write to that file:

<...>
ident:
  enable: true
  file: "/home/_mp/.oidentd.conf"
  format: "global { reply \"%user%\" }"
  username: "listener"
<...>

Then restart your ident daemon and Matterpuppeter, the puppets it creates should now be properly idented!

TODO

  • Possibly full puppeting support (as in, onboarding every single user joined on the other side), probably not as default however
  • sed-style (s///) or SMS-style edits
  • Cleanup