From 3b161f1ad91f1c4d522f2cd2357b5eca9e1a7ce4 Mon Sep 17 00:00:00 2001 From: Skylar Sadlier Date: Wed, 18 Sep 2024 22:19:49 -0600 Subject: [PATCH] - Convert examples list examples/README.md to use collapsable github sections - Add another example for sending an uploading file to a room - Add form tip for Send Message node's thread reply config option --- examples/README.md | 415 ++++++++++++++-------------- examples/paginate-room-history.json | 6 +- examples/send-image-to-room.json | 142 ++++++++++ examples/send-image-to-room.png | Bin 0 -> 22087 bytes src/matrix-send-message.html | 3 + 5 files changed, 353 insertions(+), 213 deletions(-) create mode 100644 examples/send-image-to-room.json create mode 100644 examples/send-image-to-room.png diff --git a/examples/README.md b/examples/README.md index 7aa1df6..8521c45 100644 --- a/examples/README.md +++ b/examples/README.md @@ -22,59 +22,47 @@ To try out any of the examples: ## Index +**Click the ▶ example to ▼ expand** + ### User Management -- [Get or set current user display name](#get-or-set-current-user-display-name) -- [Set user avatar using URL](#set-user-avatar-using-url) -- [Fetch user info by userId](#fetch-user-info-by-userid) -- [Create User with Shared Secret Registration](#create-user-with-shared-secret-registration) -- [Create/Edit Synapse User](#createedit-synapse-user) -- [Deactivate User](#deactivate-user) -- [Force User to Join Room](#force-user-to-join-room) +
+Get or set current user display name -### Message Handling +[View JSON](get-set-displayname.json) -- [Respond to "ping" with "pong"](#respond-to-ping-with-pong) -- [Respond to "html" with an HTML message](#respond-to-html-with-an-html-message) -- [Respond to "image" with an uploaded image](#respond-to-image-with-an-uploaded-image) -- [Respond to "file" with an uploaded file](#respond-to-file-with-an-uploaded-file) -- [Respond to "react" with a reaction](#respond-to-react-with-a-reaction) -- [Remove Messages Containing "delete"](#remove-messages-containing-delete) +This flow lets you get or set the displayname for the current user. -### Event Handling +![get-set-displayname.png](get-set-displayname.png) -- [Sending Typing Events to a Room](#sending-typing-events-to-a-room) -- [Mark all received events as read](#mark-all-received-events-as-read) -- [Fetch event by eventId and roomId](#fetch-event-by-eventid-and-roomid) -- [Paginate the entire history of a given room](#paginate-the-entire-history-of-a-given-room) -- [Paginate related events to a given eventId](#paginate-related-events-to-a-given-eventid) +
-### Room Management +
+Set user avatar using URL -- [Set room name and topic](#set-room-name-and-topic) -- [Accept Room Invites from Specific User](#accept-room-invites-from-specific-user) -- [Leave Room When Someone Says "bye"](#leave-room-when-someone-says-bye) -- [Respond to "newroom" by Creating a New Room and Inviting User](#respond-to-newroom-by-creating-a-new-room-and-inviting-user) -- [Respond to "joinroom \" by Joining Mentioned Room](#respond-to-joinroom-room_id_or_alias-by-joining-mentioned-room) -- [Kick/Ban User from Room](#kickban-user-from-room) +[View JSON](set-avatar-from-url.json) -### User Information +Inject a URL to an image and Node-RED will fetch the contents, upload to matrix, then set the user avatar to the new mxc_url. -- [Respond to "users" with Full List of Server Users](#respond-to-users-with-full-list-of-server-users) -- [Respond to "whois \" with Information about the User's Session](#respond-to-whois-user_id-with-information-about-the-users-session) -- [Respond to "rooms \" with User's Rooms](#respond-to-rooms-user_id-with-users-rooms) -- [Respond to "room_users" with Current Room's Users](#respond-to-room_users-with-current-rooms-users) +This is a good example of how to use the upload file node. -### Advanced Features +![set-avatar-from-url.png](set-avatar-from-url.png) -- [Use Function Node to Run Any Command](#use-function-node-to-run-any-command) -- [Download & Store All Received Files/Images](#download--store-all-received-filesimages) +
---- +
+Fetch user info by userId -## User Management +[View JSON](get-user.json) -### Create User with Shared Secret Registration +Note this only works for users that the bot shares a room with. It will attempt to fetch the user from local storage first and if not found will query the server for the data. + +![get-user.png](get-user.png) + +
+ +
+Create User with Shared Secret Registration [View JSON](shared-secret-registration.json) @@ -89,9 +77,10 @@ Use this flow to create users on servers with closed registration. You can also ![Shared Secret Registration](shared-secret-registration.png) ---- +
-### Create/Edit Synapse User +
+Create/Edit Synapse User [View JSON](add-user-with-admin-user.json) @@ -99,9 +88,10 @@ Allows an administrator to create or modify a user account with a specified `msg ![Create/Edit Synapse User](add-user-with-admin-user.png) ---- +
-### Deactivate User +
+Deactivate User [View JSON](deactivate-user.json) @@ -114,9 +104,10 @@ If you send "deactivate_user @test:example.com", the bot will deactivate the `@t ![Deactivate User](deactivate-user.png) ---- +
-### Force User to Join Room +
+Force User to Join Room [View JSON](force-join-room.json) @@ -129,11 +120,25 @@ If you send "force_join @test:example.com !320j90mf0394f:example.com", the bot w ![Force User to Join Room](force-join-room.png) ---- +
-## Message Handling +### Message Handling -### Respond to "ping" with "pong" +
+Upload file and send to room + +[View JSON](send-image-to-room.json) + +This flow will download an image from a given URL and upload it to the matrix server then send it to a room. + +This isn't just for images and supports any sort of file format. Videos, images, and audio files will have metadata detected automatically and appended to the message (duration, dimensions, thumbnail, etc) + +![img.png](send-image-to-room.png) + +
+ +
+Respond to "ping" with "pong" [View JSON](respond-ping-pong.json) @@ -141,9 +146,10 @@ Use this flow to respond to anyone who says "ping" with "pong" in the same room. ![Respond to "ping" with "pong"](respond-ping-pong.png) ---- +
-### Respond to "html" with an HTML Message +
+Respond to "html" with an HTML Message [View JSON](respond-to-html-with-html.json) @@ -151,39 +157,10 @@ Use this flow to respond to anyone who says "html" with an example HTML message. ![Respond to "html" with HTML Message](respond-to-html-with-html.png) ---- +
-### Respond to "image" with an Uploaded Image - -[View JSON](respond-image-with-image.json) - -You will need an image on the machine running Node-RED. In this example, `example.png` exists inside the Node-RED directory. - -**Instructions:** - -1. Place the image file (`example.png`) in the appropriate directory. -2. Import the flow and deploy it. - -![Respond to "image" with Uploaded Image](respond-image-with-image.png) - ---- - -### Respond to "file" with an Uploaded File - -[View JSON](respond-file-with-file.json) - -You will need a file on the machine running Node-RED. In this example, `sample.pdf` exists inside the Node-RED directory. - -**Instructions:** - -1. Place the file (`sample.pdf`) in the appropriate directory. -2. Import the flow and deploy it. - -![Respond to "file" with Uploaded File](respond-file-with-file.png) - ---- - -### Respond to "react" with a Reaction +
+Respond to "react" with a Reaction [View JSON](respond-react-with-reaction.json) @@ -191,9 +168,10 @@ Gives a 👍 reaction when someone says "react". ![Respond to "react" with Reaction](respond-react-with-reaction.png) ---- +
-### Remove Messages Containing "delete" +
+Remove Messages Containing "delete" [View JSON](delete-event.json) @@ -203,11 +181,99 @@ Any messages containing "delete" will be removed by the client. ![Remove Messages Containing "delete"](delete-event.png) ---- +
-## Room Management +### Event Handling -### Accept Room Invites from Specific User +
+Sending Typing Events to a Room + +[View JSON](send-typing-events.json) + +You can indicate to a room that the bot is typing and also cancel the typing event. This can be useful for making bots feel more interactive (e.g., show typing while requesting an API endpoint). + +![Sending Typing Events](send-typing-events.png) + +
+ +
+Mark all received events as read + +[View JSON](mark-all-read.json) + +With this flow anytime an event is received by the bot it will mark it as read. + +![mark-all-read.png](mark-all-read.png) + +
+ +
+Fetch event by eventId and roomId + +[View JSON](get-event.json) + +Fetch an event from Matrix by eventId and roomId + +**Instructions:** + +- Change the inject node to contain a proper eventId and roomId (topic) +- Inject the payload and you should see the result contain the event data + +![get-event.png](get-event.png) + +
+ +
+Paginate the entire history of a given room + +[View JSON](paginate-room-history.json) + +This flow iterates the entire history of a room (outputting for every page we hit). + +There is a configurable delay (currently set at 1000ms) in this flow. This is recommended, so you are not bogging down the server. + +![paginate-room-history.png](paginate-room-history.png) + +
+ +
+Paginate related events to a given eventId + +[View JSON](fetch-event-relations.json) + +Paginate through the related events to a given eventId. Related events being reactions, thread messages, message modifications, message removals, etc. This outputs once per iterated page. + +If you would rather have it output one massive list at the end of pagination use this flow: +[View Aggregated Flow JSON](fetch-event-relations-aggregated.json) + +**Instructions:** + +- Change the inject node to contain a proper eventId and roomId (topic) +- Inject the payload and you should see the result contain a list of related events for the given eventId + +![fetch-event-relations.png](fetch-event-relations.png) + +
+ +### Room Management + +
+Set room name and topic + +[View JSON](set-room-name-and-topic.json) + +Changes the specified room's name and topic to the injected values. + +There are a bunch of different settings you can change, this is just an example for these two fields to show how it's done. + +This node can also be used to read these values. + +![set-room-name-and-topic.png](set-room-name-and-topic.png) + +
+ +
+Accept Room Invites from Specific User [View JSON](accept-room-invites.json) @@ -215,9 +281,10 @@ Automatically accept room invites from a specific user. ![Accept Room Invites from Specific User](accept-room-invites.png) ---- +
-### Leave Room When Someone Says "bye" +
+Leave Room When Someone Says "bye" [View JSON](leave-room-bye.json) @@ -225,9 +292,10 @@ Leaves the room when someone says "bye". ![Leave Room When Someone Says "bye"](leave-room-bye.png) ---- +
-### Respond to "newroom" by Creating a New Room and Inviting User +
+Respond to "newroom" by Creating a New Room and Inviting User [View JSON](respond-newroom-invite.json) @@ -235,19 +303,21 @@ When someone sends "newroom", a new room will be created, and the user who sent ![Respond to "newroom" by Creating New Room](respond-newroom-invite.png) ---- +
-### Respond to "joinroom \" by Joining Mentioned Room +
+Respond to "joinroom <room_id_or_alias>" by Joining Mentioned Room [View JSON](respond-joinroom.json) -When someone sends "joinroom \", the bot will join the mentioned room. +When someone sends "joinroom <room_id_or_alias>", the bot will join the mentioned room. ![Respond to "joinroom" by Joining Room](respond-joinroom.png) ---- +
-### Kick/Ban User from Room +
+Kick/Ban User from Room [View JSON](room-kick-ban.json) @@ -258,11 +328,12 @@ When someone sends "joinroom \", the bot will join the mentio ![Kick/Ban User from Room](room-kick-ban.png) ---- +
-## User Information +### User Information -### Respond to "users" with Full List of Server Users +
+Respond to "users" with Full List of Server Users [View JSON](respond-users-list.json) @@ -275,9 +346,10 @@ When someone sends the text "users", they receive an HTML message containing all ![Respond to "users" with User List](respond-users-list.png) ---- +
-### Respond to "whois \" with Information about the User's Session +
+Respond to "whois <user_id>" with Information about the User's Session [View JSON](respond-whois.json) @@ -290,13 +362,14 @@ Lists out the user's session info, including IP address, last seen time, and use ![Respond to "whois" with User Session Info](respond-whois.png) ---- +
-### Respond to "rooms \" with User's Rooms +
+Respond to "rooms <user_id>" with User's Rooms [View JSON](respond-rooms.json) -Responds to "rooms \" with that user's rooms. If the message is just "rooms", it responds with a list of all rooms the server is participating in. +Responds to "rooms <user_id>" with that user's rooms. If the message is just "rooms", it responds with a list of all rooms the server is participating in. **Notes:** @@ -306,9 +379,10 @@ Responds to "rooms \" with that user's rooms. If the message is just " ![Respond to "rooms" with Room List](respond-rooms.png) ---- +
-### Respond to "room_users" with Current Room's Users +
+Respond to "room_users" with Current Room's Users [View JSON](respond-room-users.json) @@ -318,11 +392,12 @@ Lists the users participating in the current room. ![Respond to "room_users" with User List](respond-room-users.png) ---- +
-## Advanced Features +### Advanced Features -### Use Function Node to Run Any Command +
+Use Function Node to Run Any Command [View JSON](custom-redact-function-node.json) @@ -337,19 +412,10 @@ To view the available functions, check out the [`client.ts` file from `matrix-js ![Use Function Node to Run Commands](custom-redact-function-node.png) ---- +
-### Sending Typing Events to a Room - -[View JSON](send-typing-events.json) - -You can indicate to a room that the bot is typing and also cancel the typing event. This can be useful for making bots feel more interactive (e.g., show typing while requesting an API endpoint). - -![Sending Typing Events](send-typing-events.png) - ---- - -### Download & Store All Received Files/Images +
+Download & Store All Received Files/Images [View JSON](store-received-files.json) @@ -363,109 +429,38 @@ Downloads received files/images. If the file is encrypted, it will decrypt it fo ![Download & Store Received Files](store-received-files.png) ---- +
-### Fetch event by eventId and roomId +### Deprecated -[View JSON](get-event.json) +
+Respond to "image" with an uploaded image -Fetch an event from Matrix by eventId and roomId +[View JSON](respond-image-with-image.json) + +You will need an image on the machine running Node-RED. In this example, `example.png` exists inside the Node-RED directory. **Instructions:** -- Change the inject node to contain a proper eventId and roomId (topic) -- Inject the payload and you should see the result contain the event data +1. Place the image file (`example.png`) in the appropriate directory. +2. Import the flow and deploy it. -![get-event.png](get-event.png) +![Respond to "image" with Uploaded Image](respond-image-with-image.png) ---- +
-### Paginate related events to a given eventId +
+Respond to "file" with an uploaded file -[View JSON](fetch-event-relations.json) - -Paginate through the related events to a given eventId. Related events being reactions, thread messages, message modifications, message removals, etc. This outputs once per iterated page. - -If you would rather have it output one massive list at the end of pagination use this flow: -[View Aggregated Flow JSON](fetch-event-relations-aggregated.json) +[View JSON](respond-file-with-file.json) +You will need a file on the machine running Node-RED. In this example, `sample.pdf` exists inside the Node-RED directory. **Instructions:** -- Change the inject node to contain a proper eventId and roomId (topic) -- Inject the payload and you should see the result contain a list of related events for the given eventId - -![fetch-event-relations.png](fetch-event-relations.png) - ---- - -### Mark all received events as read - -[View JSON](mark-all-read.json) - -With this flow anytime an event is received by the bot it will mark it as read. - -![mark-all-read.png](mark-all-read.png) - ---- - -### Paginate the entire history of a given room - -[View JSON](paginate-room-history.json) - -This flow iterates the entire history of a room (outputting for every page we hit). - -![paginate-room-history.png](paginate-room-history.png) - ---- - -### Fetch user info by userId - -[View JSON](get-user.json) - -Note this only works for users that the bot shares a room with. It will attempt to fetch the user from local storage first and if not found will query the server for the data. - -![get-user.png](get-user.png) - ---- - -### Get or set current user display name - -[View JSON](get-set-displayname.json) - -This flow lets you get or set the displayname for the current user. - -![get-set-displayname.png](get-set-displayname.png) - ---- - -### Set user avatar using URL - -[View JSON](set-avatar-from-url.json) - -Inject a URL to an image and Node-RED will fetch the contents, upload to matrix, then set the user avatar to the new mxc_url. - -This is a good example of how to use the upload file node. - -![set-avatar-from-url.png](set-avatar-from-url.png) - ---- - -### Set room name and topic - -[View JSON](set-room-name-and-topic.json) - -Changes the specified room's name and topic to the injected values. - -There are a bunch of different settings you can change, this is just an example for these two fields to show how it's done. - -This node can also be used to read these values. - -![set-room-name-and-topic.png](set-room-name-and-topic.png) - ---- - - - +1. Place the file (`sample.pdf`) in the appropriate directory. +2. Import the flow and deploy it. +![Respond to "file" with Uploaded File](respond-file-with-file.png) +
diff --git a/examples/paginate-room-history.json b/examples/paginate-room-history.json index d746c18..28a1b76 100644 --- a/examples/paginate-room-history.json +++ b/examples/paginate-room-history.json @@ -15,9 +15,9 @@ "973dd418b00172c8", "3edbea9403d7c347" ], - "x": 754, + "x": 854, "y": 1339, - "w": 932, + "w": 832, "h": 182 }, { @@ -113,7 +113,7 @@ "once": false, "onceDelay": 0.1, "topic": "!example:skylar.tech", - "x": 900, + "x": 1000, "y": 1480, "wires": [ [ diff --git a/examples/send-image-to-room.json b/examples/send-image-to-room.json new file mode 100644 index 0000000..24a4f0b --- /dev/null +++ b/examples/send-image-to-room.json @@ -0,0 +1,142 @@ +[ + { + "id": "f4a0c2a9d7eed027", + "type": "group", + "z": "8fd89a0b44c61e76", + "name": "Send an uploaded file to a room", + "style": { + "label": true + }, + "nodes": [ + "8d475ab136d1ee7e", + "2524f5a9a7ea2444", + "9a149a36d6ab6470", + "9da1ed1dc33930bb", + "f93782c346d0e6ef" + ], + "x": 754, + "y": 2719, + "w": 992, + "h": 82 + }, + { + "id": "8d475ab136d1ee7e", + "type": "matrix-upload-file", + "z": "8fd89a0b44c61e76", + "g": "f4a0c2a9d7eed027", + "name": "", + "server": null, + "inputType": "msg", + "inputValue": "payload", + "fileNameType": "msg", + "fileNameValue": "filename", + "contentType": "", + "generateThumbnails": true, + "x": 1270, + "y": 2760, + "wires": [ + [ + "2524f5a9a7ea2444" + ], + [] + ] + }, + { + "id": "2524f5a9a7ea2444", + "type": "matrix-send-message", + "z": "8fd89a0b44c61e76", + "g": "f4a0c2a9d7eed027", + "name": "", + "server": null, + "roomId": "", + "message": "", + "messageType": "m.text", + "messageFormat": "", + "replaceMessage": false, + "threadReplyType": "msg", + "threadReplyValue": "isThread", + "x": 1440, + "y": 2760, + "wires": [ + [ + "f93782c346d0e6ef" + ], + [] + ] + }, + { + "id": "9a149a36d6ab6470", + "type": "http request", + "z": "8fd89a0b44c61e76", + "g": "f4a0c2a9d7eed027", + "name": "", + "method": "GET", + "ret": "bin", + "paytoqs": "ignore", + "url": "", + "tls": "", + "persist": false, + "proxy": "", + "insecureHTTPParser": false, + "authType": "", + "senderr": false, + "headers": [], + "x": 1110, + "y": 2760, + "wires": [ + [ + "8d475ab136d1ee7e" + ] + ] + }, + { + "id": "9da1ed1dc33930bb", + "type": "inject", + "z": "8fd89a0b44c61e76", + "g": "f4a0c2a9d7eed027", + "name": "", + "props": [ + { + "p": "url", + "v": "https://nodered.org/about/resources/media/node-red-icon.png", + "vt": "str" + }, + { + "p": "filename", + "v": "avatar.jpg", + "vt": "str" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "!example:skylar.tech", + "x": 900, + "y": 2760, + "wires": [ + [ + "9a149a36d6ab6470" + ] + ] + }, + { + "id": "f93782c346d0e6ef", + "type": "debug", + "z": "8fd89a0b44c61e76", + "g": "f4a0c2a9d7eed027", + "name": "Debug Output", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "x": 1620, + "y": 2760, + "wires": [] + } +] \ No newline at end of file diff --git a/examples/send-image-to-room.png b/examples/send-image-to-room.png new file mode 100644 index 0000000000000000000000000000000000000000..dbc726a05cd993e516972e07824b5c1810800c27 GIT binary patch literal 22087 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 ULmr@kAQob5aOz~Co>RoX0lmOUs{jB1 literal 0 HcmV?d00001 diff --git a/src/matrix-send-message.html b/src/matrix-send-message.html index 199b0e2..b35781b 100644 --- a/src/matrix-send-message.html +++ b/src/matrix-send-message.html @@ -89,6 +89,9 @@ +
+ If true and msg.content.['m.relates_to'].event_id or msg.eventId (parsed in that order) is provided the message will be a thread reply to the original event. +