User Tools

Site Tools


matrix_bot

This is an old revision of the document!


Matrix Bot

My first attempt at a Matrix box. I've been looking at the docs and it seems like, while there was an event stream in the past, it's now deprecated. The way to get a list of events to respond to is just to ask for them every couple of seconds. Doesn't sound very efficent, but the server seems to process the request extremely quickly (and the result is a couple of bytes).

So, a simple way to get the events is something like this:

function get_new_events($room) {
   $homeserver = "glasgow.social";
   $access_token = "access_token_goes_here"
   $url = "https://$homeserver/_matrix/client/r0/rooms/$room/messages?access_token=$access_token&from=$tracking_id";
   $data = json_decode(file_get_contents($url), true);
   return $data;
}

I wanted to add some tracking so I could say only give me events from since the last time I asked, and wanted to support multiple channels, so I put this in a loop:

// listen on these channels
$channels["#glasgow"] = "!BOrDFgeDdZZbUvfjjs:glasgow.social";
$channels["#geek"] = "!WbyXiAXhtnEqgrSftB:glasgow.social";
$tracking_file = "matrix.json";
$how_often_to_check = 3; // check every 3 seconds for new messages
while(true) {
$tracking_data = json_decode(file_get_contents($tracking_file), true);
 
$new_tracking_data = array();
foreach($channels as $channel_name=>$channel_id) {
   $messages = get_new_events($channel_id, $tracking_data[$channel_id]);
   if(!empty($messages['chunk']) and is_array($messages['chunk'])) {
      foreach($messages['chunk'] as $message) {
         if($message['type'] == "m.room.message") {
            $msg = $message['content']['body'];
            $user_id = $message['user_id'];
            echo "$user_id said $msg on $channel_name\n";
         }
      }
   }
   $new_tracking_data[$channel_id] = $messages['end'];
}
file_put_contents($tracking_file, json_encode($new_tracking_data));
sleep($how_often_to_check);
}
}

And that's basically it. You can replace the echo line with the code you need to process the message and then, optionally, reply to it (see Matrix tools).

I have a bunch of rules that my bot is listening for in IRC. So I basically just port them over and check each new message against them.

// psuedocode for my rule list
// get the rules when the program starts
$rules = $db->getRuleList();
 
 
// snip
  echo "$user_id said $msg on $channel_name\n";
  foreach($rules as $rule) {
    if(preg_match($rule['regex'], $msg)) {
      echo $rule['response'];
    }
  }
// snip

There's a bit more there where it checks access lists and include files depending on what rule it is, but you get the idea. I only have around 30 rules, so it's pretty much instant. Simple.

matrix_bot.1590822441.txt.gz ยท Last modified: 2020/05/30 08:07 by admin