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
Previous revision
matrix_bot [2020/05/30 08:17]
admin
matrix_bot [2020/05/30 11:23]
admin removed
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.