User Tools

Site Tools


matrix_bot

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision Both sides next revision
matrix_bot [2020/05/30 08:17]
admin
matrix_bot [2020/05/30 11:21]
admin
Line 1: Line 1:
 ====== Matrix Bot ====== ====== 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 pastit'​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 null result is a couple of bytes).+My first attempt at a Matrix box.  ​Fist off, wanted to get a list of events (messages). ​ There was an event stream in the docsbut that'​s ​been deprecated. ​
  
-So, a simple way to get the events is something like this:+You can get a list of events from a particular channel by sending a request to ''/​messages''​ (see the documentation here: https://​matrix.org/​docs/​api/​client-server/#​!/​Room32participation/​getRoomEvents). ​So, a simple way to get the events is something like this:
 <code php> <code php>
 function get_new_events($room) { function get_new_events($room) {
Line 13: Line 13:
 </​code>​ </​code>​
  
-I wanted ​to add some tracking so I could say only give me events ​from since the last time asked, ​and wanted to support multiple channels, so put this in a loop: +The way to get all events ​(i.e. all messages on channels you are a member of is to use the ''/​sync''​ endpoint. ​ The documentation for that is at: https://​matrix.org/​docs/​api/​client-server/#​!/​Room32participation/​sync 
-<code php> + 
-// listen on these channels + 
-$channels["#​glasgow"​] ​= "!BOrDFgeDdZZbUvfjjs:​glasgow.social";​ +===== Command line event listener ===== 
-$channels["#​geek"​] ​= "!WbyXiAXhtnEqgrSftB:​glasgow.social"; +run this in a terminal ​and it shows me everything happening on the rooms I'm in, in a simple way. 
-$tracking_file = "matrix.json";​ +<​code ​php ListToMatrix.php> 
-$how_often_to_check = 3; // check every 3 seconds for new messages+$homeserver ​= "​glasgow.social";​ 
 +$access_token ​= "access_token_goes_here"; 
 + 
 +$tracking_file = "/​tmp/​listen_matrix.json";​ 
 while(true) { while(true) {
-$tracking_data = json_decode(file_get_contents($tracking_file),​ true); 
  
-$new_tracking_data ​array(); +$since file_get_contents($tracking_file); 
-foreach($channels as $channel_name=>​$channel_id) { +$messages = get_new_events($since); 
-   $messages = get_new_events($channel_id, $tracking_data[$channel_id]); +if(!empty($messages['​rooms'​]['​join'] and is_array($messages['​rooms'​]['​join']))) { 
-   ​if(!empty($messages['​chunk']and is_array($messages['​chunk'])) { +   ​foreach($messages['​rooms'​]['​join'] as $room_id=>​$data) { 
-      foreach($messages['​chunk'] as $message) { +      foreach($data['​timeline'​]['​events'​] as $event_id=>​$event) { 
-         if($message['​type'​] == "​m.room.message"​) { +         if($event['​type'​] == "​m.room.message"​) { 
-            $msg = $message['​content'​]['​body']; +            $sender ​= $event['​sender'​];​ 
-            $user_id ​= $message['user_id']; +            $content = "​Image/​Video/​Audio";​ 
-            echo "$user_id said $msg on $channel_name\n";+            if($event['​content'​]['​msgtype'​] ​== "​m.text"​) 
 +               ​$content ​= $event['content'​]['​body']; 
 +            echo "$sender (".$rooms[$room_id]."​) $content\n";
          }          }
       }       }
    }    }
-   ​$new_tracking_data[$channel_id] = $messages['​end'​];​ 
 } }
-file_put_contents($tracking_file, ​json_encode($new_tracking_data)); +$new_tracking_data = $messages['​next_batch'​];​ 
-sleep($how_often_to_check);​+file_put_contents($tracking_file,​ $new_tracking_data);​ 
 } }
-} 
-</​code>​ 
  
-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. +function get_new_events($since) { 
-<code php> +   global $homeserver,​$access_token;​ 
-// psuedocode for my rule list +   $url = "​https:​//$homeserver/_matrix/client/​r0/​sync?​access_token=$access_token&​timeout=30000";​ 
-// get the rules when the program starts +   if(!empty($since)) 
-$rules = $db->​getRuleList();+      $url .= "&​since=$since";​ 
 +   $data = json_decode(file_get_contents($url),​ true); 
 +   ​return $data; 
 +
  
  
-// snip 
-  echo "​$user_id said $msg on $channel_name\n";​ 
-  foreach($rules as $rule) { 
-    if(preg_match($rule['​regex'​],​ $msg)) { 
-      echo $rule['​response'​];​ 
-    } 
-  } 
-// snip 
 </​code>​ </​code>​
  
-There'​s a bit more there where it checks access lists and include files depending on what rule it isbut you get the idea.  ​only have around 30 rules, so it's pretty much instant.  ​Simple.+Nowto make an actual functioning bot, replace ​the echo line with whatever you want to do (in my case, look up a list of rules [i.e. pairs of regexes and their response functions] I use in IRC from a database and act accordingly).  ​See the [[Matrix tools]] page for notes on how to post your reply to a room.