- Update examples README to make things much easier to find
- Added examples for every node - Fixed User Settings node requiring a roomId when it's not needed - Fixed the documentation for Upload File node - Get User node had unused config code that has been removed
@ -1,47 +1,95 @@
|
|||||||
# Examples
|
# Examples
|
||||||
These are examples of what is possible with the [node-red-contrib-matrix-chat](https://github.com/Skylar-Tech/node-red-contrib-matrix-chat) module for [Node-RED](https://nodered.org/)
|
|
||||||
|
|
||||||
If you want to try any of them out just copy their JSON contents from their .json file and use the hamburger menu in Node-RED to import the flow.
|
These examples showcase what is possible with the [node-red-contrib-matrix-chat](https://github.com/Skylar-Tech/node-red-contrib-matrix-chat) module for [Node-RED](https://nodered.org/).
|
||||||
|
|
||||||
Build something cool with these nodes? Feel free to submit a pull request to share it!
|
Build something cool with these nodes? Feel free to submit a pull request to share it!
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- A Matrix account
|
||||||
|
- Node-RED set up and running
|
||||||
|
- Installed `node-red-contrib-matrix-chat` module
|
||||||
|
|
||||||
|
## How to Use the Examples
|
||||||
|
|
||||||
|
To try out any of the examples:
|
||||||
|
|
||||||
|
1. Copy the JSON contents from the `.json` file linked in each example.
|
||||||
|
2. In Node-RED, use the menu to import the flow:
|
||||||
|
- Click the hamburger menu (top right corner).
|
||||||
|
- Select **Import**.
|
||||||
|
- Paste the JSON and click **Import**.
|
||||||
|
|
||||||
## Index
|
## Index
|
||||||
|
|
||||||
|
### 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 User with Shared Secret Registration](#create-user-with-shared-secret-registration)
|
||||||
- [Create/Edit Synapse User](#createedit-synapse-user)
|
- [Create/Edit Synapse User](#createedit-synapse-user)
|
||||||
- [Use function node to run any command](#use-function-node-to-run-any-command)
|
- [Deactivate User](#deactivate-user)
|
||||||
|
- [Force User to Join Room](#force-user-to-join-room)
|
||||||
|
|
||||||
|
### Message Handling
|
||||||
|
|
||||||
- [Respond to "ping" with "pong"](#respond-to-ping-with-pong)
|
- [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 "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 "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 "file" with an uploaded file](#respond-to-file-with-an-uploaded-file)
|
||||||
- [Respond to "react" with a reaction](#respond-to-react-with-a-reaction)
|
- [Respond to "react" with a reaction](#respond-to-react-with-a-reaction)
|
||||||
- [Accept room invites from specific user](#accept-room-invites-from-specific-user)
|
- [Remove Messages Containing "delete"](#remove-messages-containing-delete)
|
||||||
- [Leave room when someone says "bye"](#leave-room-when-someone-says-bye)
|
|
||||||
- [Remove messages containing "delete"](#remove-messages-containing-delete)
|
|
||||||
- [Respond to "users" with full list of server users](#respond-to-users-with-full-list-of-server-users)
|
|
||||||
- [Respond to "newroom" by creating new room and inviting user](#respond-to-newroom-by-creating-new-room-and-inviting-user)
|
|
||||||
- [Respond to "joinroom <room_id_or_alias>" by joining mentioned room](#respond-to-joinroom-room_id_or_alias-by-joining-mentioned-room)
|
|
||||||
- [Respond to "rooms <user_id>" with user's rooms (list server's rooms if <user_id> is left blank)](#respond-to-rooms-user_id-with-users-rooms-list-servers-rooms-if-user_id-is-left-blank)
|
|
||||||
- [Respond to "whois <user_id>" with information about the user's session](#respond-to-whois-user_id-with-information-about-the-users-session)
|
|
||||||
- [Respond to "room_users" with current room's users](#respond-to-room_users-with-current-rooms-users)
|
|
||||||
- [Sending typing events to a room](#sending-typing-events-to-a-room)
|
|
||||||
- [Download & store all received files/images](#download--store-all-received-filesimages)
|
|
||||||
- [Kick/Ban user from room](#kickban-user-from-room)
|
|
||||||
- [Deactivate user](#deactivate-user)
|
|
||||||
|
|
||||||
|
### Event Handling
|
||||||
|
|
||||||
### Create user with Shared Secret Registration
|
- [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 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 \<room_id_or_alias\>" by Joining Mentioned Room](#respond-to-joinroom-room_id_or_alias-by-joining-mentioned-room)
|
||||||
|
- [Kick/Ban User from Room](#kickban-user-from-room)
|
||||||
|
|
||||||
|
### User Information
|
||||||
|
|
||||||
|
- [Respond to "users" with Full List of Server Users](#respond-to-users-with-full-list-of-server-users)
|
||||||
|
- [Respond to "whois \<user_id\>" with Information about the User's Session](#respond-to-whois-user_id-with-information-about-the-users-session)
|
||||||
|
- [Respond to "rooms \<user_id\>" 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)
|
||||||
|
|
||||||
|
### Advanced Features
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## User Management
|
||||||
|
|
||||||
|
### Create User with Shared Secret Registration
|
||||||
|
|
||||||
[View JSON](shared-secret-registration.json)
|
[View JSON](shared-secret-registration.json)
|
||||||
|
|
||||||
Use this flow to create users on servers with closed registration. You also use this endpoint to create your first admin user as it is the same as running the local python script on the server. This requires your registration secret from your homeserver.yaml Synapse server configuration file.
|
Use this flow to create users on servers with closed registration. You can also use this endpoint to create your first admin user, as it is the same as running the local Python script on the server. This requires your registration secret from your `homeserver.yaml` Synapse server configuration file.
|
||||||
|
|
||||||
Edit the object on the inject node to the user/pass combo you want to create and hit the inject button (to the left of the inject node).
|
**Instructions:**
|
||||||
|
|
||||||
|
1. Edit the object on the inject node to specify the desired username and password.
|
||||||
|
2. Click the inject button (to the left of the inject node) to create the user.
|
||||||
|
|
||||||
**Note:** This only works on Synapse servers.
|
**Note:** This only works on Synapse servers.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Create/Edit Synapse User
|
### Create/Edit Synapse User
|
||||||
|
|
||||||
@ -49,222 +97,375 @@ Edit the object on the inject node to the user/pass combo you want to create and
|
|||||||
|
|
||||||
Allows an administrator to create or modify a user account with a specified `msg.userId`.
|
Allows an administrator to create or modify a user account with a specified `msg.userId`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Use function node to run any command
|
### Deactivate User
|
||||||
|
|
||||||
[View JSON](custom-redact-function-node.json)
|
[View JSON](deactivate-user.json)
|
||||||
|
|
||||||
If we do not have a node for something you want to do you can do this manually with a function node. We now have a node for removing events but this is still a good example.
|
If you send "deactivate_user @test:example.com", the bot will deactivate the `@test:example.com` account on the server.
|
||||||
|
|
||||||
**Note:** You should make sure to catch any errors in your function node otherwise you could cause Node-RED to crash.
|
**Note:**
|
||||||
|
|
||||||
To view what sort of functions you have access to check out the `client.ts` file from `matrix-js-sdk` [here](https://github.com/matrix-org/matrix-js-sdk/blob/master/src/client.ts).
|
- This requires the bot to be a server admin.
|
||||||
|
- **WARNING:** Accounts that are deleted cannot be restored. If you want to temporarily disable a user, consider modifying the user instead.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Force User to Join Room
|
||||||
|
|
||||||
|
[View JSON](force-join-room.json)
|
||||||
|
|
||||||
|
If you send "force_join @test:example.com !320j90mf0394f:example.com", the bot will force the user `@test:example.com` into room `!320j90mf0394f:example.com`.
|
||||||
|
|
||||||
|
**Note:**
|
||||||
|
|
||||||
|
- This requires the bot to be a server admin.
|
||||||
|
- This only works for rooms on the same server.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Message Handling
|
||||||
|
|
||||||
### Respond to "ping" with "pong"
|
### Respond to "ping" with "pong"
|
||||||
|
|
||||||
[View JSON](respond-ping-pong.json)
|
[View JSON](respond-ping-pong.json)
|
||||||
|
|
||||||
Use this flow to respond to anyone that says "ping" with "pong" into the same room.
|
Use this flow to respond to anyone who says "ping" with "pong" in the same room.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Respond to "html" with an HTML Message
|
||||||
### Respond to "html" with an HTML message
|
|
||||||
|
|
||||||
[View JSON](respond-to-html-with-html.json)
|
[View JSON](respond-to-html-with-html.json)
|
||||||
|
|
||||||
Use this flow to respond to anyone that says "html" with an example HTML message. This shows how easy it is to send HTML.
|
Use this flow to respond to anyone who says "html" with an example HTML message. This shows how easy it is to send HTML content.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Respond to "image" with an Uploaded Image
|
||||||
### Respond to "image" with an uploaded image
|
|
||||||
|
|
||||||
[View JSON](respond-image-with-image.json)
|
[View JSON](respond-image-with-image.json)
|
||||||
|
|
||||||
You will need an image on the machine running Node-RED. In this case example.png exists inside the Node-RED directory.
|
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 "file" with an uploaded file
|
---
|
||||||
|
|
||||||
|
### Respond to "file" with an Uploaded File
|
||||||
|
|
||||||
[View JSON](respond-file-with-file.json)
|
[View JSON](respond-file-with-file.json)
|
||||||
|
|
||||||
You will need a file on the machine running Node-RED. In this case sample.pdf exists inside the Node-RED directory.
|
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 "react" with a reaction
|
---
|
||||||
|
|
||||||
|
### Respond to "react" with a Reaction
|
||||||
|
|
||||||
[View JSON](respond-react-with-reaction.json)
|
[View JSON](respond-react-with-reaction.json)
|
||||||
|
|
||||||
Give a 👍 reaction when someone says "react"
|
Gives a 👍 reaction when someone says "react".
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Remove Messages Containing "delete"
|
||||||
### Accept room invites from specific user
|
|
||||||
|
|
||||||
[View JSON](accept-room-invites.json)
|
|
||||||
|
|
||||||
Accept room invites from specific user.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Leave room when someone says bye
|
|
||||||
|
|
||||||
[View JSON](leave-room-bye.json)
|
|
||||||
|
|
||||||
Leave room when someone says "bye".
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Remove messages containing "delete"
|
|
||||||
|
|
||||||
[View JSON](delete-event.json)
|
[View JSON](delete-event.json)
|
||||||
|
|
||||||
Any messages containing "delete" will try to be removed by the client.
|
Any messages containing "delete" will be removed by the client.
|
||||||
|
|
||||||

|
**Note:** The bot needs appropriate permissions to remove messages.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Respond to "users" with full list of server users
|
## Room Management
|
||||||
|
|
||||||
[View JSON](respond-users-list.json)
|
### Accept Room Invites from Specific User
|
||||||
|
|
||||||
When someone sends the text "users" they get a HTML message back containing all the current users on the server. If your server has a lot of users this paginates and sends a message with 25 users per message.
|
[View JSON](accept-room-invites.json)
|
||||||
|
|
||||||
This requires admin privileges.
|
Automatically accept room invites from a specific user.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Respond to "newroom" by creating new room and inviting user
|
### Leave Room When Someone Says "bye"
|
||||||
|
|
||||||
[View JSON](respond-users-list.json)
|
[View JSON](leave-room-bye.json)
|
||||||
|
|
||||||
When someone sends "newroom" a new room will be created and the user that said the message will be invited. The client will also send a welcome message into the new room.
|
Leaves the room when someone says "bye".
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Respond to "joinroom <room_id_or_alias>" by joining mentioned room
|
### Respond to "newroom" by Creating a New Room and Inviting User
|
||||||
|
|
||||||
|
[View JSON](respond-newroom-invite.json)
|
||||||
|
|
||||||
|
When someone sends "newroom", a new room will be created, and the user who sent the message will be invited. The bot will also send a welcome message into the new room.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Respond to "joinroom \<room_id_or_alias\>" by Joining Mentioned Room
|
||||||
|
|
||||||
[View JSON](respond-joinroom.json)
|
[View JSON](respond-joinroom.json)
|
||||||
|
|
||||||
When someone sends "newroom" a new room will be created and the user that said the message will be invited. The client will also send a welcome message into the new room.
|
When someone sends "joinroom \<room_id_or_alias\>", the bot will join the mentioned room.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Respond to "rooms <user_id>" with user's rooms (list server's rooms if <user_id> is left blank)
|
---
|
||||||
|
|
||||||
[View JSON](respond-rooms.json)
|
### Kick/Ban User from Room
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Note: If there are a lot of rooms this may fail to send the message as it is too large. This also only works for user's that are on the current server.
|
|
||||||
|
|
||||||
This requires admin privileges.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### Respond to "whois <user_id>" with information about the user's session
|
|
||||||
|
|
||||||
[View JSON](respond-whois.json)
|
|
||||||
|
|
||||||
This lists out the user's session info. Each session contains the IP address, when it was last seen, and the user agent. Useful to find out more about a specific user on your server.
|
|
||||||
|
|
||||||
Note: If there are a lot of sessions this may fail to send the message as it is too large. This also only works for user's that are on the current server.
|
|
||||||
|
|
||||||
This requires admin privileges.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### Respond to "room_users" with current room's users
|
|
||||||
|
|
||||||
[View JSON](respond-room-users.json)
|
|
||||||
|
|
||||||
List out the users participating in a room.
|
|
||||||
|
|
||||||
Note: If there are a lot of users in the room this will fail to send due to a large message error.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### Download & store all received files/images
|
|
||||||
|
|
||||||
[View JSON](store-received-files.json)
|
|
||||||
|
|
||||||
Download received files/images. If the file is encrypted it will decrypt it for you. The decrypt node downloads the file for you otherwise you need to use a HTTP Request node to download the file.
|
|
||||||
|
|
||||||
Note: You may need to edit the storage directory for this to work. Default action is to create a `downloads` folder in the Node-RED directory and places files in that but there is a good chance your Node-RED instance doesn't have access to write to this directory.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### Sending typing events to a room
|
|
||||||
|
|
||||||
[View JSON](send-typing-events.json)
|
|
||||||
|
|
||||||
You can tell a room that Node-RED is writing a message and also cancel the writing event. This can be useful for making bots feel more interactive (show typing while requesting API endpoint for example).
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### Kick/Ban user from room
|
|
||||||
|
|
||||||
[View JSON](room-kick-ban.json)
|
[View JSON](room-kick-ban.json)
|
||||||
|
|
||||||
If you say "kick @test:example.com" the bot will kick @test:example.com from the current room.
|
- If you say "kick @test:example.com", the bot will kick `@test:example.com` from the current room.
|
||||||
|
- If you say "ban @test:example.com", the bot will ban `@test:example.com` from the current room.
|
||||||
|
|
||||||
If you say "ban @test:example.com" the bot will ban @test:example.com from the current room.
|
**Note:** This requires the bot to have permissions to kick/ban in the current room.
|
||||||
|
|
||||||
Note: This requires the bot to have permissions to kick/ban in the current room.
|

|
||||||
|
|
||||||

|
---
|
||||||
|
|
||||||
|
## User Information
|
||||||
|
|
||||||
|
### Respond to "users" with Full List of Server Users
|
||||||
|
|
||||||
|
[View JSON](respond-users-list.json)
|
||||||
|
|
||||||
|
When someone sends the text "users", they receive an HTML message containing all the current users on the server. If your server has many users, this paginates and sends messages with 25 users per message.
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
|
||||||
|
- This requires admin privileges.
|
||||||
|
- If there are many users, the bot may send multiple messages due to message size limits.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Respond to "whois \<user_id\>" with Information about the User's Session
|
||||||
|
|
||||||
|
[View JSON](respond-whois.json)
|
||||||
|
|
||||||
|
Lists out the user's session info, including IP address, last seen time, and user agent. Useful for finding out more about a specific user on your server.
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
|
||||||
|
- This requires admin privileges.
|
||||||
|
- If the user has many sessions, the message may be too large to send in one piece.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Respond to "rooms \<user_id\>" with User's Rooms
|
||||||
|
|
||||||
|
[View JSON](respond-rooms.json)
|
||||||
|
|
||||||
|
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:**
|
||||||
|
|
||||||
|
- This requires admin privileges.
|
||||||
|
- If there are many rooms, the message may be too large to send in one piece.
|
||||||
|
- This only works for users on the current server.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Respond to "room_users" with Current Room's Users
|
||||||
|
|
||||||
|
[View JSON](respond-room-users.json)
|
||||||
|
|
||||||
|
Lists the users participating in the current room.
|
||||||
|
|
||||||
|
**Note:** If there are many users in the room, the message may be too large to send.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Advanced Features
|
||||||
|
|
||||||
|
### Use Function Node to Run Any Command
|
||||||
|
|
||||||
|
[View JSON](custom-redact-function-node.json)
|
||||||
|
|
||||||
|
If there isn't a node for something you want to do, you can use a function node to manually execute commands. For example, you can redact events (remove messages).
|
||||||
|
|
||||||
|
**Instructions:**
|
||||||
|
|
||||||
|
- Use the function node to write custom commands using the `matrix-js-sdk` client.
|
||||||
|
- Make sure to catch any errors in your function node to prevent Node-RED from crashing.
|
||||||
|
|
||||||
|
To view the available functions, check out the [`client.ts` file from `matrix-js-sdk`](https://github.com/matrix-org/matrix-js-sdk/blob/master/src/client.ts).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 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).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Download & Store All Received Files/Images
|
||||||
|
|
||||||
|
[View JSON](store-received-files.json)
|
||||||
|
|
||||||
|
Downloads received files/images. If the file is encrypted, it will decrypt it for you. The decrypt node downloads the file; otherwise, you need to use an HTTP Request node to download the file.
|
||||||
|
|
||||||
|
**Instructions:**
|
||||||
|
|
||||||
|
- You may need to edit the storage directory for this to work.
|
||||||
|
- By default, files are saved in a `downloads` folder in the Node-RED directory.
|
||||||
|
- Ensure that Node-RED has permission to write to the specified directory.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 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)
|
||||||
|
|
||||||
|
|
||||||
### Deactivate user
|
**Instructions:**
|
||||||
|
|
||||||
[View JSON](deactivate-user.json)
|
- 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
|
||||||
|
|
||||||
If you say "deactivate_user @test:example.com" the bot will deactivate the @test:example.com account on the server.
|

|
||||||
|
|
||||||
Note: This requires the bot to be a server admin.
|
---
|
||||||
|
|
||||||
WARNING: Accounts that are deleted cannot be restored. If you want to temp-disable edit the user instead.
|
### Mark all received events as read
|
||||||
|
|
||||||

|
[View JSON](mark-all-read.json)
|
||||||
|
|
||||||
### Force user to join room
|
With this flow anytime an event is received by the bot it will mark it as read.
|
||||||
|
|
||||||
[View JSON](force-join-room.json)
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 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).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 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 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 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 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
If you say "force_join @test:example.com !320j90mf0394f:example.com" the bot will force the user `@test:example.com` into room `!320j90mf0394f:example.com`
|
|
||||||
|
|
||||||
Note: This requires the bot to be a server admin. This also only works for rooms on the same server.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Paginate room history
|
|
||||||
|
|
||||||
|
141
examples/fetch-event-relations-aggregated.json
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "10a897739618e1f3",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Aggregates paginated matrix event relations and outputs the full set after reaching the last page",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"83d9261d8fef6c29",
|
||||||
|
"c2e00e38bbeea60a",
|
||||||
|
"8c1df4f49b913bf8",
|
||||||
|
"4be02d632d13cebf",
|
||||||
|
"09fc3b3f18df27af"
|
||||||
|
],
|
||||||
|
"x": 774,
|
||||||
|
"y": 939,
|
||||||
|
"w": 772,
|
||||||
|
"h": 142
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "83d9261d8fef6c29",
|
||||||
|
"type": "matrix-fetch-relations",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "10a897739618e1f3",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomType": "msg",
|
||||||
|
"roomValue": "topic",
|
||||||
|
"eventIdType": "msg",
|
||||||
|
"eventIdValue": "eventId",
|
||||||
|
"relationTypeType": "json",
|
||||||
|
"relationTypeValue": "null",
|
||||||
|
"eventTypeType": "json",
|
||||||
|
"eventTypeValue": "null",
|
||||||
|
"directionType": "str",
|
||||||
|
"directionValue": "b",
|
||||||
|
"limitType": "json",
|
||||||
|
"limitValue": "null",
|
||||||
|
"recurseType": "bool",
|
||||||
|
"recurseValue": "false",
|
||||||
|
"fromType": "msg",
|
||||||
|
"fromValue": "payload.next_batch",
|
||||||
|
"toType": "json",
|
||||||
|
"toValue": "null",
|
||||||
|
"x": 1180,
|
||||||
|
"y": 1040,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"c2e00e38bbeea60a"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"4be02d632d13cebf"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c2e00e38bbeea60a",
|
||||||
|
"type": "function",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "10a897739618e1f3",
|
||||||
|
"name": "Loop - output on finish",
|
||||||
|
"func": "// you will want to use a unique flow_key \n// if you duplicate this node multiple times\nlet flow_key = \"relations_\" + msg.topic;\nlet relations = flow.get(flow_key) || [];\n\n// add our chunk to the flow variable\nrelations.push(...msg.payload.chunk);\n\nif(msg.payload.next_batch) {\n // loop around for more records\n flow.set(flow_key, relations);\n return [null, msg];\n}\n\n// if msg.payload.next_batch is unset we have reached the end\nflow.set(flow_key, undefined);\nmsg.payload = relations;\nreturn [msg, null];",
|
||||||
|
"outputs": 2,
|
||||||
|
"noerr": 0,
|
||||||
|
"initialize": "",
|
||||||
|
"finalize": "",
|
||||||
|
"libs": [],
|
||||||
|
"x": 1180,
|
||||||
|
"y": 980,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"8c1df4f49b913bf8"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"83d9261d8fef6c29"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8c1df4f49b913bf8",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "10a897739618e1f3",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1420,
|
||||||
|
"y": 980,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4be02d632d13cebf",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "10a897739618e1f3",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1410,
|
||||||
|
"y": 1040,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "09fc3b3f18df27af",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "10a897739618e1f3",
|
||||||
|
"name": "",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"p": "topic",
|
||||||
|
"vt": "str"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "eventId",
|
||||||
|
"v": "$example",
|
||||||
|
"vt": "str"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "!example:skylar.tech",
|
||||||
|
"x": 920,
|
||||||
|
"y": 1040,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"83d9261d8fef6c29"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/fetch-event-relations.png
Normal file
After Width: | Height: | Size: 26 KiB |
103
examples/get-event.json
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "13e21fb561dd6367",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Get event by eventId and roomId",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"79aa7974c32c41e7",
|
||||||
|
"f895181928491647",
|
||||||
|
"687ab5804c6ab05c",
|
||||||
|
"c731a6923324de48"
|
||||||
|
],
|
||||||
|
"x": 814,
|
||||||
|
"y": 759,
|
||||||
|
"w": 692,
|
||||||
|
"h": 122
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "79aa7974c32c41e7",
|
||||||
|
"type": "matrix-get-event",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "13e21fb561dd6367",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomIdType": "msg",
|
||||||
|
"roomIdValue": "topic",
|
||||||
|
"eventIdType": "msg",
|
||||||
|
"eventIdValue": "eventId",
|
||||||
|
"x": 1200,
|
||||||
|
"y": 820,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"f895181928491647"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"687ab5804c6ab05c"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "f895181928491647",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "13e21fb561dd6367",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1380,
|
||||||
|
"y": 800,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "687ab5804c6ab05c",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "13e21fb561dd6367",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1370,
|
||||||
|
"y": 840,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c731a6923324de48",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "13e21fb561dd6367",
|
||||||
|
"name": "",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"p": "topic",
|
||||||
|
"vt": "str"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "eventId",
|
||||||
|
"v": "$example",
|
||||||
|
"vt": "str"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "!example:skylar.tech",
|
||||||
|
"x": 960,
|
||||||
|
"y": 820,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"79aa7974c32c41e7"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/get-event.png
Normal file
After Width: | Height: | Size: 17 KiB |
201
examples/get-set-displayname.json
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "844cdfc6e3fc3207",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Get current display name",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"9807698e516450ec",
|
||||||
|
"3f700b2d3458a1e8",
|
||||||
|
"78ff7e5088a08ff6",
|
||||||
|
"0ae57f85687ba6b3"
|
||||||
|
],
|
||||||
|
"x": 754,
|
||||||
|
"y": 2119,
|
||||||
|
"w": 612,
|
||||||
|
"h": 122
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9807698e516450ec",
|
||||||
|
"type": "matrix-user-settings",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "844cdfc6e3fc3207",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomId": null,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"t": "get",
|
||||||
|
"p": "display_name",
|
||||||
|
"to": "payload",
|
||||||
|
"tot": "msg",
|
||||||
|
"ls": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"x": 1020,
|
||||||
|
"y": 2180,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"78ff7e5088a08ff6"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"0ae57f85687ba6b3"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3f700b2d3458a1e8",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "844cdfc6e3fc3207",
|
||||||
|
"name": "",
|
||||||
|
"props": [],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "",
|
||||||
|
"x": 850,
|
||||||
|
"y": 2180,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"9807698e516450ec"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "78ff7e5088a08ff6",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "844cdfc6e3fc3207",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1240,
|
||||||
|
"y": 2160,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "0ae57f85687ba6b3",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "844cdfc6e3fc3207",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1230,
|
||||||
|
"y": 2200,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "289fac90afc8bfa6",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Set current display name",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"8f166980f4bfe6a4",
|
||||||
|
"c31399d30d9ea44f",
|
||||||
|
"c7984555f4ad668e",
|
||||||
|
"634935af5451baf9"
|
||||||
|
],
|
||||||
|
"x": 754,
|
||||||
|
"y": 2259,
|
||||||
|
"w": 612,
|
||||||
|
"h": 122
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8f166980f4bfe6a4",
|
||||||
|
"type": "matrix-user-settings",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "289fac90afc8bfa6",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomId": null,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"t": "set",
|
||||||
|
"p": "display_name",
|
||||||
|
"to": "payload",
|
||||||
|
"tot": "msg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"x": 1020,
|
||||||
|
"y": 2320,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"c7984555f4ad668e"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"634935af5451baf9"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c31399d30d9ea44f",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "289fac90afc8bfa6",
|
||||||
|
"name": "",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"p": "payload"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "",
|
||||||
|
"payload": "New Name",
|
||||||
|
"payloadType": "str",
|
||||||
|
"x": 860,
|
||||||
|
"y": 2320,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"8f166980f4bfe6a4"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c7984555f4ad668e",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "289fac90afc8bfa6",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1240,
|
||||||
|
"y": 2300,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "634935af5451baf9",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "289fac90afc8bfa6",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1230,
|
||||||
|
"y": 2340,
|
||||||
|
"wires": []
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/get-set-displayname.png
Normal file
After Width: | Height: | Size: 32 KiB |
99
examples/get-user.json
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "fdbc1eb4cc492b04",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Fetch user info by userId",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"8869afc68deeede0",
|
||||||
|
"e29636a733134aef",
|
||||||
|
"15c5caf17e83263c",
|
||||||
|
"52a65daa26891471"
|
||||||
|
],
|
||||||
|
"x": 754,
|
||||||
|
"y": 1939,
|
||||||
|
"w": 552,
|
||||||
|
"h": 122
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8869afc68deeede0",
|
||||||
|
"type": "matrix-get-user",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "fdbc1eb4cc492b04",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"userType": "msg",
|
||||||
|
"userValue": "userId",
|
||||||
|
"propertyType": "msg",
|
||||||
|
"propertyValue": "user",
|
||||||
|
"x": 1000,
|
||||||
|
"y": 2000,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"15c5caf17e83263c"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"52a65daa26891471"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e29636a733134aef",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "fdbc1eb4cc492b04",
|
||||||
|
"name": "",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"p": "userId",
|
||||||
|
"v": "@skylord123:skylar.tech",
|
||||||
|
"vt": "str"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "",
|
||||||
|
"x": 850,
|
||||||
|
"y": 2000,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"8869afc68deeede0"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "15c5caf17e83263c",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "fdbc1eb4cc492b04",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1180,
|
||||||
|
"y": 1980,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "52a65daa26891471",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "fdbc1eb4cc492b04",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1170,
|
||||||
|
"y": 2020,
|
||||||
|
"wires": []
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/get-user.png
Normal file
After Width: | Height: | Size: 14 KiB |
99
examples/mark-all-read.json
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "a8bd7a89b91a93c4",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Mark all received events as read",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"f9e49ebbc4bda431",
|
||||||
|
"c58fce26efb45b27",
|
||||||
|
"c8feb91421fcbbb3",
|
||||||
|
"e6d52159a6cfe0c0"
|
||||||
|
],
|
||||||
|
"x": 754,
|
||||||
|
"y": 1579,
|
||||||
|
"w": 632,
|
||||||
|
"h": 122
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "f9e49ebbc4bda431",
|
||||||
|
"type": "matrix-mark-read",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "a8bd7a89b91a93c4",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomType": "msg",
|
||||||
|
"roomValue": "topic",
|
||||||
|
"eventIdType": "msg",
|
||||||
|
"eventIdValue": "eventId",
|
||||||
|
"x": 1070,
|
||||||
|
"y": 1640,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"c8feb91421fcbbb3"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"e6d52159a6cfe0c0"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c58fce26efb45b27",
|
||||||
|
"type": "matrix-receive",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "a8bd7a89b91a93c4",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomId": "",
|
||||||
|
"acceptOwnEvents": false,
|
||||||
|
"acceptText": true,
|
||||||
|
"acceptEmotes": true,
|
||||||
|
"acceptStickers": true,
|
||||||
|
"acceptReactions": true,
|
||||||
|
"acceptFiles": true,
|
||||||
|
"acceptAudio": true,
|
||||||
|
"acceptImages": true,
|
||||||
|
"acceptVideos": true,
|
||||||
|
"acceptLocations": true,
|
||||||
|
"x": 860,
|
||||||
|
"y": 1640,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"f9e49ebbc4bda431"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c8feb91421fcbbb3",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "a8bd7a89b91a93c4",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1260,
|
||||||
|
"y": 1620,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e6d52159a6cfe0c0",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "a8bd7a89b91a93c4",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1250,
|
||||||
|
"y": 1660,
|
||||||
|
"wires": []
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/mark-all-read.png
Normal file
After Width: | Height: | Size: 17 KiB |
173
examples/paginate-room-history.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "1317b79375a65579",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Paginate the entire history of a given room",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"e8fc071b3f81fdee",
|
||||||
|
"33937ba1e74ed92d",
|
||||||
|
"4aadbf1c37d2ac8b",
|
||||||
|
"e4025b7df45f3d91",
|
||||||
|
"973dd418b00172c8",
|
||||||
|
"3edbea9403d7c347"
|
||||||
|
],
|
||||||
|
"x": 754,
|
||||||
|
"y": 1339,
|
||||||
|
"w": 932,
|
||||||
|
"h": 182
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e8fc071b3f81fdee",
|
||||||
|
"type": "matrix-paginate-room",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "1317b79375a65579",
|
||||||
|
"name": "Paginate Room",
|
||||||
|
"server": null,
|
||||||
|
"roomType": "msg",
|
||||||
|
"roomValue": "topic",
|
||||||
|
"paginateKeyType": "msg",
|
||||||
|
"paginateKeyValue": "paginateKey",
|
||||||
|
"paginateBackwardsType": "msg",
|
||||||
|
"paginateBackwardsValue": "paginateBackwards",
|
||||||
|
"pageSizeType": "msg",
|
||||||
|
"pageSizeValue": "pageSize",
|
||||||
|
"x": 1280,
|
||||||
|
"y": 1480,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"973dd418b00172c8"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"4aadbf1c37d2ac8b"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "33937ba1e74ed92d",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "1317b79375a65579",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1560,
|
||||||
|
"y": 1380,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4aadbf1c37d2ac8b",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "1317b79375a65579",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1530,
|
||||||
|
"y": 1480,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e4025b7df45f3d91",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "1317b79375a65579",
|
||||||
|
"name": "",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"p": "topic",
|
||||||
|
"vt": "str"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "paginateKey",
|
||||||
|
"v": "",
|
||||||
|
"vt": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "paginateBackwards",
|
||||||
|
"v": "true",
|
||||||
|
"vt": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "pageSize",
|
||||||
|
"v": "25",
|
||||||
|
"vt": "num"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "timeout",
|
||||||
|
"v": "1000",
|
||||||
|
"vt": "num"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "!example:skylar.tech",
|
||||||
|
"x": 900,
|
||||||
|
"y": 1480,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"e8fc071b3f81fdee"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "973dd418b00172c8",
|
||||||
|
"type": "function",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "1317b79375a65579",
|
||||||
|
"name": "Loop - return each chunk",
|
||||||
|
"func": "node.status({\n fill: \"green\",\n text: `${msg.start} - ${msg.end} ${msg.payload ? '' : 'DONE'}`\n});\n\nif(msg.payload.length) {\n // we have more records so output to both\n return [msg, msg];\n}\n\n// no more records so only send to output 1\nreturn [msg, null];",
|
||||||
|
"outputs": 2,
|
||||||
|
"noerr": 0,
|
||||||
|
"initialize": "",
|
||||||
|
"finalize": "",
|
||||||
|
"libs": [],
|
||||||
|
"x": 1290,
|
||||||
|
"y": 1400,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"33937ba1e74ed92d"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"3edbea9403d7c347"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3edbea9403d7c347",
|
||||||
|
"type": "delay",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "1317b79375a65579",
|
||||||
|
"name": "msg.delay",
|
||||||
|
"pauseType": "delayv",
|
||||||
|
"timeout": "0",
|
||||||
|
"timeoutUnits": "seconds",
|
||||||
|
"rate": "1",
|
||||||
|
"nbRateUnits": "1",
|
||||||
|
"rateUnits": "second",
|
||||||
|
"randomFirst": "1",
|
||||||
|
"randomLast": "5",
|
||||||
|
"randomUnits": "seconds",
|
||||||
|
"drop": false,
|
||||||
|
"allowrate": false,
|
||||||
|
"outputs": 1,
|
||||||
|
"x": 1550,
|
||||||
|
"y": 1420,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"e8fc071b3f81fdee"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/paginate-room-history.png
Normal file
After Width: | Height: | Size: 31 KiB |
122
examples/set-avatar-from-url.json
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "4cac7bbe81dd3a54",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Set new avatar image from remote image URL",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"91f08bf02decd653",
|
||||||
|
"44a586ebac1fb619",
|
||||||
|
"d3bd4a0d4e1520a3",
|
||||||
|
"e9e591def93615c5"
|
||||||
|
],
|
||||||
|
"x": 754,
|
||||||
|
"y": 2419,
|
||||||
|
"w": 712,
|
||||||
|
"h": 82
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "91f08bf02decd653",
|
||||||
|
"type": "http request",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "4cac7bbe81dd3a54",
|
||||||
|
"name": "",
|
||||||
|
"method": "GET",
|
||||||
|
"ret": "bin",
|
||||||
|
"paytoqs": "ignore",
|
||||||
|
"url": "",
|
||||||
|
"tls": "",
|
||||||
|
"persist": false,
|
||||||
|
"proxy": "",
|
||||||
|
"insecureHTTPParser": false,
|
||||||
|
"authType": "",
|
||||||
|
"senderr": false,
|
||||||
|
"headers": [],
|
||||||
|
"x": 1010,
|
||||||
|
"y": 2460,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"e9e591def93615c5"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "44a586ebac1fb619",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "4cac7bbe81dd3a54",
|
||||||
|
"name": "",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"p": "url",
|
||||||
|
"v": "https://nodered.org/about/resources/media/node-red-icon.png",
|
||||||
|
"vt": "str"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "filename",
|
||||||
|
"v": "avatar.jpg",
|
||||||
|
"vt": "str"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "",
|
||||||
|
"x": 850,
|
||||||
|
"y": 2460,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"91f08bf02decd653"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d3bd4a0d4e1520a3",
|
||||||
|
"type": "matrix-user-settings",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "4cac7bbe81dd3a54",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomId": null,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"t": "set",
|
||||||
|
"p": "avatar_url",
|
||||||
|
"to": "payload.url",
|
||||||
|
"tot": "msg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"x": 1360,
|
||||||
|
"y": 2460,
|
||||||
|
"wires": [
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e9e591def93615c5",
|
||||||
|
"type": "matrix-upload-file",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "4cac7bbe81dd3a54",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"inputType": "msg",
|
||||||
|
"inputValue": "payload",
|
||||||
|
"fileNameType": "msg",
|
||||||
|
"fileNameValue": "filename",
|
||||||
|
"contentType": "",
|
||||||
|
"generateThumbnails": true,
|
||||||
|
"x": 1190,
|
||||||
|
"y": 2460,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"d3bd4a0d4e1520a3"
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/set-avatar-from-url.png
Normal file
After Width: | Height: | Size: 14 KiB |
120
examples/set-room-name-and-topic.json
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "2e2bb3f8521150c0",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Set room name and topic",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"610648ad6bd73072",
|
||||||
|
"aca9be4e86e111f3",
|
||||||
|
"7f5e16c4f6c7885f",
|
||||||
|
"915ce202570af51a"
|
||||||
|
],
|
||||||
|
"x": 674,
|
||||||
|
"y": 2539,
|
||||||
|
"w": 732,
|
||||||
|
"h": 122
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "610648ad6bd73072",
|
||||||
|
"type": "matrix-room-state-events",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "2e2bb3f8521150c0",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomType": "msg",
|
||||||
|
"roomValue": "topic",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"t": "set",
|
||||||
|
"p": "m.room.name",
|
||||||
|
"to": "roomName",
|
||||||
|
"tot": "msg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "set",
|
||||||
|
"p": "m.room.topic",
|
||||||
|
"to": "description",
|
||||||
|
"tot": "msg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"x": 1050,
|
||||||
|
"y": 2600,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"7f5e16c4f6c7885f"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"915ce202570af51a"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "aca9be4e86e111f3",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "2e2bb3f8521150c0",
|
||||||
|
"name": "",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"p": "topic",
|
||||||
|
"vt": "str"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "roomName",
|
||||||
|
"v": "Test Room",
|
||||||
|
"vt": "str"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "description",
|
||||||
|
"v": "This is a test room for my Node-RED bot",
|
||||||
|
"vt": "str"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "!example:skylar.tech",
|
||||||
|
"x": 820,
|
||||||
|
"y": 2600,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"610648ad6bd73072"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7f5e16c4f6c7885f",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "2e2bb3f8521150c0",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1280,
|
||||||
|
"y": 2580,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "915ce202570af51a",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "2e2bb3f8521150c0",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1270,
|
||||||
|
"y": 2620,
|
||||||
|
"wires": []
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/set-room-name-and-topic.png
Normal file
After Width: | Height: | Size: 18 KiB |
141
examples/view-event-relations.json
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "ab09dd64e9c48bba",
|
||||||
|
"type": "group",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"name": "Pages through matrix event relations, delivering results one page at a time",
|
||||||
|
"style": {
|
||||||
|
"label": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
"ed98bce4958c4203",
|
||||||
|
"501758e233cc42d9",
|
||||||
|
"edb9af1a22e2e17f",
|
||||||
|
"4734e9ee26fe0812",
|
||||||
|
"fc27f2058f9c934b"
|
||||||
|
],
|
||||||
|
"x": 754,
|
||||||
|
"y": 1139,
|
||||||
|
"w": 892,
|
||||||
|
"h": 142
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ed98bce4958c4203",
|
||||||
|
"type": "matrix-fetch-relations",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "ab09dd64e9c48bba",
|
||||||
|
"name": "",
|
||||||
|
"server": null,
|
||||||
|
"roomType": "msg",
|
||||||
|
"roomValue": "topic",
|
||||||
|
"eventIdType": "msg",
|
||||||
|
"eventIdValue": "eventId",
|
||||||
|
"relationTypeType": "json",
|
||||||
|
"relationTypeValue": "null",
|
||||||
|
"eventTypeType": "json",
|
||||||
|
"eventTypeValue": "null",
|
||||||
|
"directionType": "str",
|
||||||
|
"directionValue": "b",
|
||||||
|
"limitType": "json",
|
||||||
|
"limitValue": "null",
|
||||||
|
"recurseType": "bool",
|
||||||
|
"recurseValue": "false",
|
||||||
|
"fromType": "msg",
|
||||||
|
"fromValue": "payload.next_batch",
|
||||||
|
"toType": "json",
|
||||||
|
"toValue": "null",
|
||||||
|
"x": 1280,
|
||||||
|
"y": 1240,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"edb9af1a22e2e17f"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"fc27f2058f9c934b"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "501758e233cc42d9",
|
||||||
|
"type": "inject",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "ab09dd64e9c48bba",
|
||||||
|
"name": "",
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"p": "topic",
|
||||||
|
"vt": "str"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "eventId",
|
||||||
|
"v": "$example",
|
||||||
|
"vt": "str"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repeat": "",
|
||||||
|
"crontab": "",
|
||||||
|
"once": false,
|
||||||
|
"onceDelay": 0.1,
|
||||||
|
"topic": "!example:skylar.tech",
|
||||||
|
"x": 900,
|
||||||
|
"y": 1240,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"ed98bce4958c4203"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "edb9af1a22e2e17f",
|
||||||
|
"type": "function",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "ab09dd64e9c48bba",
|
||||||
|
"name": "Loop - return each chunk",
|
||||||
|
"func": "if(msg.payload.next_batch) {\n // we have more records so output to both\n return [msg, msg];\n}\n\n// no more records so only send to output 1\nreturn [msg, null];",
|
||||||
|
"outputs": 2,
|
||||||
|
"noerr": 0,
|
||||||
|
"initialize": "",
|
||||||
|
"finalize": "",
|
||||||
|
"libs": [],
|
||||||
|
"x": 1290,
|
||||||
|
"y": 1180,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"4734e9ee26fe0812"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"ed98bce4958c4203"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4734e9ee26fe0812",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "ab09dd64e9c48bba",
|
||||||
|
"name": "Debug Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1520,
|
||||||
|
"y": 1180,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fc27f2058f9c934b",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "8fd89a0b44c61e76",
|
||||||
|
"g": "ab09dd64e9c48bba",
|
||||||
|
"name": "Error Output",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"x": 1510,
|
||||||
|
"y": 1240,
|
||||||
|
"wires": []
|
||||||
|
}
|
||||||
|
]
|
@ -12,25 +12,19 @@
|
|||||||
<input type="text" id="node-input-user">
|
<input type="text" id="node-input-user">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-property"><i class="fa fa-user"></i> Property</label>
|
<label for="node-input-property"><i class="fa fa-user"></i> Output Property</label>
|
||||||
<input type="text" id="node-input-property">
|
<input type="text" id="node-input-property">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row form-tips">
|
<div class="form-row form-tips">
|
||||||
This is the property the user data object will be set to
|
This is the property the user data object will be set to
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row" style="margin-bottom:0;">
|
|
||||||
<label><i class="fa fa-list"></i> <span data-i18n="change.label.rules"></span></label>
|
|
||||||
</div>
|
|
||||||
<div class="form-row node-input-rule-container-row">
|
|
||||||
<ol id="node-input-rule-container"></ol>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/html" data-help-name="matrix-get-user">
|
<script type="text/html" data-help-name="matrix-get-user">
|
||||||
<h3>Details</h3>
|
<h3>Details</h3>
|
||||||
<p>
|
<p>
|
||||||
Get data for a user. Data includes display name, avatar URL, presence, last active, currently active, and latest user events.
|
Get data for a user. Data includes display name, avatar URL, presence, last active, currently active, and latest user events. You must share a room with the user. This tried to fetch the user from local storage and if it does not exist will then ask the server.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Inputs</h3>
|
<h3>Inputs</h3>
|
||||||
@ -62,27 +56,6 @@
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
(function(){
|
(function(){
|
||||||
var roomEventTypeOptions = [
|
|
||||||
{ value: "m.room.name", label: "m.room.name" },
|
|
||||||
{ value: "m.room.topic", label: "m.room.topic" },
|
|
||||||
{ value: "m.room.avatar", label: "m.room.avatar" },
|
|
||||||
{ value: "m.room.power_levels", label: "m.room.power_levels" },
|
|
||||||
{ value: "m.room.guest_access", label: "m.room.guest_access" },
|
|
||||||
{ value: "m.room.join_rules", label: "m.room.join_rules" },
|
|
||||||
{ value: "m.room.canonical_alias", label: "m.room.canonical_alias" },
|
|
||||||
{ value: "m.room.history_visibility", label: "m.room.history_visibility" },
|
|
||||||
{ value: "m.room.server_acl", label: "m.room.server_acl" },
|
|
||||||
{ value: "m.room.pinned_events", label: "m.room.pinned_events"},
|
|
||||||
{ value: "m.space.child", label: "m.space.child" },
|
|
||||||
{ value: "m.space.parent", label: "m.space.parent" },
|
|
||||||
];
|
|
||||||
var defaultRules = [{
|
|
||||||
t: "set",
|
|
||||||
p: roomEventTypeOptions[0].value,
|
|
||||||
to: "payload",
|
|
||||||
tot: "msg"
|
|
||||||
}];
|
|
||||||
|
|
||||||
function isInvalidProperty(v,vt) {
|
function isInvalidProperty(v,vt) {
|
||||||
if (/msg|flow|global/.test(vt)) {
|
if (/msg|flow|global/.test(vt)) {
|
||||||
if (!RED.utils.validatePropertyExpression(v)) {
|
if (!RED.utils.validatePropertyExpression(v)) {
|
||||||
@ -129,208 +102,12 @@
|
|||||||
})
|
})
|
||||||
.typedInput('value', this.propertyValue)
|
.typedInput('value', this.propertyValue)
|
||||||
.typedInput('type', this.propertyType);
|
.typedInput('type', this.propertyType);
|
||||||
|
|
||||||
var set = "Set";
|
|
||||||
var to = "to the value";
|
|
||||||
var toValueLabel = "to the property";
|
|
||||||
var search = this._("change.action.search");
|
|
||||||
var replace = this._("change.action.replace");
|
|
||||||
var regex = this._("change.label.regex");
|
|
||||||
|
|
||||||
function createPropertyValue(row2_1, row2_2, type, defaultType) {
|
|
||||||
var propValInput = $('<input/>',{class:"node-input-rule-property-value",type:"text"})
|
|
||||||
.appendTo(row2_1)
|
|
||||||
.typedInput({
|
|
||||||
default: defaultType || (type === 'set' ? 'str' : 'msg'),
|
|
||||||
types: (type === 'set' ? ['msg','flow','global','str','json','jsonata'] : ['msg', 'flow', 'global'])
|
|
||||||
});
|
|
||||||
|
|
||||||
var lsLabel = $('<label style="padding-left: 130px;"></label>').appendTo(row2_2);
|
|
||||||
var localStorageEl = $('<input type="checkbox" class="node-input-rule-property-localStorage" style="width: auto; margin: 0 6px 0 0">').appendTo(lsLabel);
|
|
||||||
$('<span>').text("Fetch from local storage").appendTo(lsLabel);
|
|
||||||
|
|
||||||
propValInput.on("change", function(evt,type,val) {
|
|
||||||
row2_2.toggle(type === "msg" || type === "flow" || type === "global" || type === "env");
|
|
||||||
})
|
|
||||||
return [propValInput, localStorageEl];
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#node-input-rule-container').css('min-height','150px').css('min-width','450px').editableList({
|
|
||||||
addItem: function(container,i,opt) {
|
|
||||||
var rule = opt;
|
|
||||||
if (!rule.hasOwnProperty('t')) {
|
|
||||||
rule = {t:"set",p:roomEventTypeOptions[0].value,to:"payload",tot:"msg"};
|
|
||||||
}
|
|
||||||
if (rule.t === "set" && !rule.tot) {
|
|
||||||
if (rule.to.indexOf("msg.") === 0 && !rule.tot) {
|
|
||||||
rule.to = rule.to.substring(4);
|
|
||||||
rule.tot = "msg";
|
|
||||||
} else {
|
|
||||||
rule.tot = "str";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container.css({
|
|
||||||
overflow: 'hidden',
|
|
||||||
whiteSpace: 'nowrap'
|
|
||||||
});
|
|
||||||
let fragment = document.createDocumentFragment();
|
|
||||||
var row1 = $('<div/>',{style:"display:flex; align-items: center"}).appendTo(fragment);
|
|
||||||
var row2 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
|
|
||||||
var row3 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
|
|
||||||
var row4 = $('<div/>',{style:"display:flex;margin-top:8px;align-items: baseline"}).appendTo(fragment);
|
|
||||||
|
|
||||||
var selectField = $('<select/>',{class:"node-input-rule-type",style:"width:110px; margin-right:10px;"}).appendTo(row1);
|
|
||||||
var selectOptions = [
|
|
||||||
{v:"set",l:"Set"},
|
|
||||||
{v:"get",l:"Get"}
|
|
||||||
];
|
|
||||||
for (var x=0; x<selectOptions.length; x++) {
|
|
||||||
selectField.append($("<option></option>").val(selectOptions[x].v).text(selectOptions[x].l));
|
|
||||||
}
|
|
||||||
|
|
||||||
var propertyName = $('<input/>',{class:"node-input-rule-property-name",type:"text"})
|
|
||||||
.appendTo(row1)
|
|
||||||
.autoComplete({
|
|
||||||
minLength:0,
|
|
||||||
search: function(val) {
|
|
||||||
if(!val) {
|
|
||||||
return roomEventTypeOptions.sort(function(A,B){return A.i-B.i});
|
|
||||||
}
|
|
||||||
var matches = [];
|
|
||||||
roomEventTypeOptions.map((x) => x.value).forEach(v => {
|
|
||||||
var i = v.toLowerCase().indexOf(val.toLowerCase());
|
|
||||||
if (i > -1) {
|
|
||||||
matches.push({
|
|
||||||
value: v,
|
|
||||||
label: v,
|
|
||||||
i: i
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
matches.sort(function(A,B){return A.i-B.i})
|
|
||||||
return matches
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on('focus', function(evt){
|
|
||||||
// following is a fix so autocomplete will show list on focus
|
|
||||||
if(!evt.isTrigger) {
|
|
||||||
evt.stopPropagation();
|
|
||||||
$(this).trigger("keyup.red-ui-autoComplete");
|
|
||||||
}
|
|
||||||
}).on("keyup", function(evt) {
|
|
||||||
// following allows autocomplete to display even when backspace/delete is used
|
|
||||||
if (evt.keyCode === 8 || evt.keyCode === 46) {
|
|
||||||
evt.stopPropagation();
|
|
||||||
$(this).trigger("keyup.red-ui-autoComplete");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var row2_1 = $('<div/>', {style:"display:flex;align-items: baseline"}).appendTo(row2);
|
|
||||||
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
|
||||||
.text(toValueLabel)
|
|
||||||
.appendTo(row2_1);
|
|
||||||
|
|
||||||
var row2_2 = $('<div/>', {style:"margin-top: 4px;"}).appendTo(row2);
|
|
||||||
|
|
||||||
var row3_1 = $('<div/>', {style:"display:flex;align-items: baseline"}).appendTo(row3);
|
|
||||||
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
|
||||||
.text(search)
|
|
||||||
.appendTo(row3_1);
|
|
||||||
|
|
||||||
var row3_2 = $('<div/>',{style:"display:flex;margin-top:8px;align-items: baseline"}).appendTo(row3);
|
|
||||||
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
|
||||||
.text(replace)
|
|
||||||
.appendTo(row3_2);
|
|
||||||
|
|
||||||
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
|
||||||
.text(to)
|
|
||||||
.appendTo(row4);
|
|
||||||
|
|
||||||
let propertyValue = null;
|
|
||||||
let localStorageEl = null;
|
|
||||||
let fromValue = null;
|
|
||||||
let toValue = null;
|
|
||||||
|
|
||||||
selectField.on("change", function() {
|
|
||||||
var type = $(this).val();
|
|
||||||
if (propertyValue) {
|
|
||||||
propertyValue.typedInput('hide');
|
|
||||||
}
|
|
||||||
if (fromValue) {
|
|
||||||
fromValue.typedInput('hide');
|
|
||||||
}
|
|
||||||
if (toValue) {
|
|
||||||
toValue.typedInput('hide');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!propertyValue) {
|
|
||||||
var parts = createPropertyValue(row2_1, row2_2, type);
|
|
||||||
propertyValue = parts[0];
|
|
||||||
localStorageEl = parts[1];
|
|
||||||
} else {
|
|
||||||
propertyValue.typedInput('types', (type === 'set' ? ['msg','flow','global','str','json','jsonata'] : ['msg', 'flow', 'global']));
|
|
||||||
}
|
|
||||||
|
|
||||||
propertyValue.typedInput('show');
|
|
||||||
row2.show();
|
|
||||||
if(type === 'get') {
|
|
||||||
localStorageEl.parent().show();
|
|
||||||
} else {
|
|
||||||
localStorageEl.parent().hide();
|
|
||||||
}
|
|
||||||
row3.hide();
|
|
||||||
row4.hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
selectField.val(rule.t);
|
|
||||||
propertyName.val(rule.p);
|
|
||||||
if (rule.t === "set" || rule.t === "get") {
|
|
||||||
var parts = createPropertyValue(row2_1, row2_2, rule.t, rule.tot);
|
|
||||||
propertyValue = parts[0];
|
|
||||||
localStorageEl = parts[1];
|
|
||||||
propertyValue.typedInput('value',rule.to);
|
|
||||||
localStorageEl.prop("checked", !!rule.ls);
|
|
||||||
if(rule.t === 'get') {
|
|
||||||
localStorageEl.parent().show();
|
|
||||||
} else {
|
|
||||||
localStorageEl.parent().hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selectField.change();
|
|
||||||
container[0].appendChild(fragment);
|
|
||||||
},
|
|
||||||
removable: true,
|
|
||||||
sortable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var i=0; i<this.rules.length; i++) {
|
|
||||||
var rule = this.rules[i];
|
|
||||||
$("#node-input-rule-container").editableList('addItem',rule);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
oneditsave: function() {
|
oneditsave: function() {
|
||||||
this.userType = $("#node-input-user").typedInput('type');
|
this.userType = $("#node-input-user").typedInput('type');
|
||||||
this.userValue = $("#node-input-user").typedInput('value');
|
this.userValue = $("#node-input-user").typedInput('value');
|
||||||
this.propertyType = $("#node-input-property").typedInput('type');
|
this.propertyType = $("#node-input-property").typedInput('type');
|
||||||
this.propertyValue = $("#node-input-property").typedInput('value');
|
this.propertyValue = $("#node-input-property").typedInput('value');
|
||||||
var rules = $("#node-input-rule-container").editableList('items');
|
|
||||||
var node = this;
|
|
||||||
node.rules= [];
|
|
||||||
rules.each(function(i) {
|
|
||||||
var rule = $(this);
|
|
||||||
var type = rule.find(".node-input-rule-type").val();
|
|
||||||
var r = {
|
|
||||||
t:type,
|
|
||||||
p:rule.find(".node-input-rule-property-name").val(),
|
|
||||||
to:rule.find(".node-input-rule-property-value").typedInput('value'),
|
|
||||||
tot:rule.find(".node-input-rule-property-value").typedInput('type')
|
|
||||||
};
|
|
||||||
|
|
||||||
if (r.t === "get" && rule.find(".node-input-rule-property-localStorage").prop("checked")) {
|
|
||||||
r.ls = true;
|
|
||||||
}
|
|
||||||
node.rules.push(r);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
oneditresize: function(size) {
|
oneditresize: function(size) {
|
||||||
var rows = $("#dialog-form>div:not(.node-input-rule-container-row)");
|
var rows = $("#dialog-form>div:not(.node-input-rule-container-row)");
|
||||||
|
@ -105,59 +105,69 @@
|
|||||||
|
|
||||||
<script type="text/html" data-help-name="matrix-upload-file">
|
<script type="text/html" data-help-name="matrix-upload-file">
|
||||||
<h3>Details</h3>
|
<h3>Details</h3>
|
||||||
<p>Upload a file to the matrix homeserver. Returns a payload that can then be chained to a Send Message node to post the file to a room, or you can use the mxc_url to update a user or room avatar.</p>
|
<p>Upload a file to the Matrix homeserver. Returns a payload that can then be chained to a Send Message node to post the file to a room, or you can use the mxc_url to update a user or room avatar. The node supports uploading files, auto-detecting their types, and generating optional thumbnails for images and videos. Encrypted uploads are also supported.</p>
|
||||||
|
|
||||||
<h3>Inputs</h3>
|
<h3>Inputs</h3>
|
||||||
<dl class="message-properties">
|
<dl class="message-properties">
|
||||||
<dt>msg.payload
|
<dt>msg.payload
|
||||||
<span class="property-type">string | Buffer</span>
|
<span class="property-type">string | Buffer</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd> If this is not a buffer it assumes it is a path to the file. </dd>
|
<dd> A path to the file (string) or a file buffer (Buffer) to upload. If a buffer is provided, you must specify the filename for accurate type detection.</dd>
|
||||||
|
|
||||||
<dt>msg.topic
|
<dt>msg.filename
|
||||||
<span class="property-type">string</span>
|
<span class="property-type">string</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd> Room ID to send file to. Ignored if configured on the node, otherwise required.</dd>
|
<dd> The name of the file to upload. If not provided, the filename is auto-detected from the path, but this may lead to inaccuracies in file type detection.</dd>
|
||||||
|
|
||||||
<dt class="optional">msg.filename
|
<dt>msg.body
|
||||||
<span class="property-type">string | null</span>
|
<span class="property-type">string | null</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd> name of the file to upload. You REALLY should pass this if you want the file type to be detected correctly. If no filename is provided it will be auto-detected but note that this is not perfect (for example: .doc word files are detected incorrectly as application/x-cfb) and only works with binary files.</dd>
|
<dd> The display name for the file when rendered in the chat. If left empty, the default display name is "Attachment".</dd>
|
||||||
|
|
||||||
<dt class="optional">msg.body
|
|
||||||
<span class="property-type">string | null</span>
|
|
||||||
</dt>
|
|
||||||
<dd> this will be the display name the client will see when rendered in their chat client. If this is left empty it will just display as "Attachment".</dd>
|
|
||||||
|
|
||||||
<dt class="optional">msg.contentType
|
<dt class="optional">msg.contentType
|
||||||
<span class="property-type">string | null</span>
|
<span class="property-type">string | null</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd> Content <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>. If set this forces the mime type. If you do not provide this it will try to be auto-detected.</dd>
|
<dd> Optional MIME Type of the file. If not provided, the type will be auto-detected based on the filename or buffer. If the detection fails, it will default to "text/plain".</dd>
|
||||||
|
|
||||||
<dt class="optional">msg.content
|
<dt class="optional">msg.encrypted
|
||||||
<span class="property-type">object | null</span>
|
<span class="property-type">boolean</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd> craft your own msg.content to send to the server. If defined then <code>msg.filename</code>, <code>msg.contentType</code>, <code>msg.body</code>, and <code>msg.payload</code> aren't required since the file already exists.</dd>
|
<dd> Set to true if the file should be uploaded with encryption. The node handles encryption automatically if this is enabled.</dd>
|
||||||
|
|
||||||
|
<dt class="optional">msg.generateThumbnails
|
||||||
|
<span class="property-type">boolean</span>
|
||||||
|
</dt>
|
||||||
|
<dd> Set to true to generate thumbnails for image or video uploads. Thumbnails are generated automatically for supported types.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h3>Outputs</h3>
|
<h3>Outputs</h3>
|
||||||
<ol class="node-ports">
|
<ol class="node-ports">
|
||||||
<li>Success
|
<li>Success
|
||||||
<dl class="message-properties">
|
<dl class="message-properties">
|
||||||
|
<dt>msg.payload <span class="property-type">object</span></dt>
|
||||||
|
<dd>An object containing details of the uploaded file, including the URL (mxc URI), the MIME type, size, and any generated thumbnail information.</dd>
|
||||||
|
|
||||||
<dt>msg.eventId <span class="property-type">string</span></dt>
|
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||||
<dd>the eventId from the posted message.</dd>
|
<dd>The eventId of the uploaded file message.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
<li>Error
|
<li>Error
|
||||||
<dl class="message-properties">
|
<dl class="message-properties">
|
||||||
<dt>msg.error <span class="property-type">string</span></dt>
|
<dt>msg.error <span class="property-type">string</span></dt>
|
||||||
<dd>the error that occurred.</dd>
|
<dd>A description of the error that occurred during the upload.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
<h3>Additional Notes</h3>
|
||||||
|
<ul>
|
||||||
|
<li>The node supports generating thumbnails for images and video files if configured. For videos, the thumbnail is generated from the first frame.</li>
|
||||||
|
<li>Encrypted uploads require no additional configuration beyond setting msg.encrypted to true. The node handles encryption and returns the necessary decryption information.</li>
|
||||||
|
<li>The file type is auto-detected based on the filename or the content buffer. You can override this by setting the msg.contentType manually.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h3>References</h3>
|
<h3>References</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME Types</a> - description of <code>msg.contentType</code> format</li>
|
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME Types</a> - description of <code>msg.contentType</code> format</li>
|
||||||
</ul>
|
</ul>
|
||||||
</script>
|
</script>
|
||||||
|
@ -40,14 +40,6 @@ module.exports = function(RED) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.topic = node.roomId || msg.topic;
|
|
||||||
if(!msg.topic) {
|
|
||||||
msg.error = "Room must be specified in msg.topic or in configuration";
|
|
||||||
node.error(msg.error, msg);
|
|
||||||
node.send([null, msg]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let getterErrors = {},
|
let getterErrors = {},
|
||||||
setterErrors = {};
|
setterErrors = {};
|
||||||
|
|
||||||
|