This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
matrix_bot [2020/05/30 08:17] admin |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== 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 null result is a couple of bytes). | ||
- | So, a simple way to get the events is something like this: | ||
- | <code php> | ||
- | 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; | ||
- | } | ||
- | </code> | ||
- | |||
- | 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: | ||
- | <code php> | ||
- | // 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); | ||
- | } | ||
- | } | ||
- | </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. | ||
- | <code php> | ||
- | // 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 | ||
- | </code> | ||
- | |||
- | 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. |