commit
78f8ab7abb
@ -26,9 +26,7 @@ The following is supported from this package:
|
|||||||
- Get a user list from a room
|
- Get a user list from a room
|
||||||
- Kick user from room
|
- Kick user from room
|
||||||
- Ban user from room
|
- Ban user from room
|
||||||
- Join a room
|
- Join, Create, Invite, and Leave rooms
|
||||||
- Create a room
|
|
||||||
- Invite to a room
|
|
||||||
- Synapse admin API to force add user to room (requires bot to be in same room already)
|
- Synapse admin API to force add user to room (requires bot to be in same room already)
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ Build something cool with these nodes? Feel free to submit a pull request to sha
|
|||||||
- [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)
|
||||||
|
- [Leave room when someone says "bye"](#leave-room-when-someone-says-bye)
|
||||||
- [Remove messages containing "delete"](#remove-messages-containing-delete)
|
- [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 "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 "newroom" by creating new room and inviting user](#respond-to-newroom-by-creating-new-room-and-inviting-user)
|
||||||
@ -113,6 +115,26 @@ Give a 👍 reaction when someone says "react"
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Accept room invites from specific user
|
||||||
|
|
||||||
|
[View JSON](accept-room-invites.json)
|
||||||
|
|
||||||
|
Accept room invites from specific user.
|
||||||
|
|
||||||
|
![accept-room-invites.png](accept-room-invites.png)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Leave room when someone says bye
|
||||||
|
|
||||||
|
[View JSON](leave-room-bye.json)
|
||||||
|
|
||||||
|
Leave room when someone says "bye".
|
||||||
|
|
||||||
|
![leave-room-bye.png](leave-room-bye.png)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Remove messages containing "delete"
|
### Remove messages containing "delete"
|
||||||
|
|
||||||
[View JSON](delete-event.json)
|
[View JSON](delete-event.json)
|
||||||
|
94
examples/accept-room-invites.json
Normal file
94
examples/accept-room-invites.json
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "64f76474ff7a3727",
|
||||||
|
"type": "matrix-room-invite",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "",
|
||||||
|
"server": "8da0ef83f77f8e24",
|
||||||
|
"roomId": null,
|
||||||
|
"x": 270,
|
||||||
|
"y": 2380,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"22f6056fa5bc5bd0"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6d6f304a0a6342b8",
|
||||||
|
"type": "matrix-join-room",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "",
|
||||||
|
"server": "8da0ef83f77f8e24",
|
||||||
|
"x": 770,
|
||||||
|
"y": 2380,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"1409ebb4a0e65663"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"1409ebb4a0e65663"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "22f6056fa5bc5bd0",
|
||||||
|
"type": "switch",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "msg.userId == @skylord123:skylar.tech",
|
||||||
|
"property": "userId",
|
||||||
|
"propertyType": "msg",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"t": "eq",
|
||||||
|
"v": "@skylord123:skylar.tech",
|
||||||
|
"vt": "str"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checkall": "true",
|
||||||
|
"repair": false,
|
||||||
|
"outputs": 1,
|
||||||
|
"x": 520,
|
||||||
|
"y": 2380,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"6d6f304a0a6342b8"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "043f74e6d76b1eb0",
|
||||||
|
"type": "comment",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "Only accept room invites from specific user",
|
||||||
|
"info": "",
|
||||||
|
"x": 360,
|
||||||
|
"y": 2340,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1409ebb4a0e65663",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"targetType": "full",
|
||||||
|
"statusVal": "",
|
||||||
|
"statusType": "auto",
|
||||||
|
"x": 910,
|
||||||
|
"y": 2380,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8da0ef83f77f8e24",
|
||||||
|
"type": "matrix-server-config",
|
||||||
|
"name": null,
|
||||||
|
"autoAcceptRoomInvites": false,
|
||||||
|
"enableE2ee": true,
|
||||||
|
"global": true
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/accept-room-invites.png
Normal file
BIN
examples/accept-room-invites.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
103
examples/leave-room-bye.json
Normal file
103
examples/leave-room-bye.json
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "997c354038202dba",
|
||||||
|
"type": "comment",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "Leave room when someone says \"bye\"",
|
||||||
|
"info": "",
|
||||||
|
"x": 350,
|
||||||
|
"y": 2520,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "69c4ea189be94feb",
|
||||||
|
"type": "matrix-receive",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "",
|
||||||
|
"server": "8da0ef83f77f8e24",
|
||||||
|
"roomId": "",
|
||||||
|
"acceptText": true,
|
||||||
|
"acceptEmotes": true,
|
||||||
|
"acceptStickers": true,
|
||||||
|
"acceptReactions": true,
|
||||||
|
"acceptFiles": true,
|
||||||
|
"acceptAudio": true,
|
||||||
|
"acceptImages": true,
|
||||||
|
"acceptLocations": true,
|
||||||
|
"x": 280,
|
||||||
|
"y": 2560,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"19e1d64b63ae8a1f"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "19e1d64b63ae8a1f",
|
||||||
|
"type": "switch",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "msg.payload == bye",
|
||||||
|
"property": "payload",
|
||||||
|
"propertyType": "msg",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"t": "eq",
|
||||||
|
"v": "bye",
|
||||||
|
"vt": "str"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checkall": "true",
|
||||||
|
"repair": false,
|
||||||
|
"outputs": 1,
|
||||||
|
"x": 480,
|
||||||
|
"y": 2560,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"db0e51f8e7793f92"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "db0e51f8e7793f92",
|
||||||
|
"type": "matrix-leave-room",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "",
|
||||||
|
"server": "8da0ef83f77f8e24",
|
||||||
|
"roomId": null,
|
||||||
|
"x": 670,
|
||||||
|
"y": 2560,
|
||||||
|
"wires": [
|
||||||
|
[
|
||||||
|
"3791f551bf0e4fc4"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"3791f551bf0e4fc4"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3791f551bf0e4fc4",
|
||||||
|
"type": "debug",
|
||||||
|
"z": "f025a8b9fbd1b054",
|
||||||
|
"name": "",
|
||||||
|
"active": true,
|
||||||
|
"tosidebar": true,
|
||||||
|
"console": false,
|
||||||
|
"tostatus": false,
|
||||||
|
"complete": "true",
|
||||||
|
"targetType": "full",
|
||||||
|
"statusVal": "",
|
||||||
|
"statusType": "auto",
|
||||||
|
"x": 810,
|
||||||
|
"y": 2560,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8da0ef83f77f8e24",
|
||||||
|
"type": "matrix-server-config",
|
||||||
|
"name": null,
|
||||||
|
"autoAcceptRoomInvites": false,
|
||||||
|
"enableE2ee": true,
|
||||||
|
"global": true
|
||||||
|
}
|
||||||
|
]
|
BIN
examples/leave-room-bye.png
Normal file
BIN
examples/leave-room-bye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
13836
package-lock.json
generated
13836
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@ -1,14 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red-contrib-matrix-chat",
|
"name": "node-red-contrib-matrix-chat",
|
||||||
"version": "0.6.1",
|
"version": "0.7.0",
|
||||||
"description": "Matrix chat server client for Node-RED",
|
"description": "Matrix chat server client for Node-RED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs-extra": "^10.0.1",
|
"abort-controller": "^3.0.0",
|
||||||
|
"fs-extra": "^11.1.0",
|
||||||
"got": "^12.0.2",
|
"got": "^12.0.2",
|
||||||
"isomorphic-webcrypto": "^2.3.8",
|
"isomorphic-webcrypto": "^2.3.8",
|
||||||
"matrix-js-sdk": "^16.0.0",
|
"matrix-js-sdk": "^22.0.0",
|
||||||
|
"node-fetch": "^3.3.0",
|
||||||
"node-localstorage": "^2.2.1",
|
"node-localstorage": "^2.2.1",
|
||||||
"olm": "https://gitlab.matrix.org/matrix-org/olm/-/package_files/271/download",
|
"olm": "https://gitlab.matrix.org/matrix-org/olm/-/package_files/472/download",
|
||||||
|
"request": "^2.88.2",
|
||||||
"utf8": "^3.0.0"
|
"utf8": "^3.0.0"
|
||||||
},
|
},
|
||||||
"node-red": {
|
"node-red": {
|
||||||
@ -23,7 +26,9 @@
|
|||||||
"matrix-react": "src/matrix-react.js",
|
"matrix-react": "src/matrix-react.js",
|
||||||
"matrix-create-room": "src/matrix-create-room.js",
|
"matrix-create-room": "src/matrix-create-room.js",
|
||||||
"matrix-invite-room": "src/matrix-invite-room.js",
|
"matrix-invite-room": "src/matrix-invite-room.js",
|
||||||
|
"matrix-room-invite": "src/matrix-room-invite.js",
|
||||||
"matrix-join-room": "src/matrix-join-room.js",
|
"matrix-join-room": "src/matrix-join-room.js",
|
||||||
|
"matrix-leave-room": "src/matrix-leave-room.js",
|
||||||
"matrix-crypt-file": "src/matrix-crypt-file.js",
|
"matrix-crypt-file": "src/matrix-crypt-file.js",
|
||||||
"matrix-room-kick": "src/matrix-room-kick.js",
|
"matrix-room-kick": "src/matrix-room-kick.js",
|
||||||
"matrix-room-ban": "src/matrix-room-ban.js",
|
"matrix-room-ban": "src/matrix-room-ban.js",
|
||||||
@ -42,9 +47,9 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"node-red",
|
"node-red",
|
||||||
"matrix",
|
"matrix",
|
||||||
"support",
|
"chat",
|
||||||
"bot",
|
"chatbot",
|
||||||
"chat"
|
"federated"
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
roomId: { value: null },
|
roomId: { value: null },
|
||||||
},
|
},
|
||||||
label: function() {
|
label: function() {
|
||||||
return this.name || "Room Invite";
|
return this.name || "Invite to Room";
|
||||||
},
|
},
|
||||||
paletteLabel: 'Room Invite'
|
paletteLabel: 'Invite to Room'
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
63
src/matrix-leave-room.html
Normal file
63
src/matrix-leave-room.html
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('matrix-leave-room', {
|
||||||
|
category: 'matrix',
|
||||||
|
color: '#00b7ca',
|
||||||
|
icon: "matrix.png",
|
||||||
|
outputLabels: ["success", "error"],
|
||||||
|
inputs: 1,
|
||||||
|
outputs: 2,
|
||||||
|
defaults: {
|
||||||
|
name: { value: null },
|
||||||
|
server: { value: "", type: "matrix-server-config" },
|
||||||
|
roomId: { value: null },
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.name || "Leave Room";
|
||||||
|
},
|
||||||
|
paletteLabel: 'Leave Room'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-template-name="matrix-leave-room">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-server"><i class="fa fa-user"></i> Matrix Server Config</label>
|
||||||
|
<input type="text" id="node-input-server">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-help-name="matrix-leave-room">
|
||||||
|
<h3>Details</h3>
|
||||||
|
<p>
|
||||||
|
This node leaves a room
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Inputs</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.topic
|
||||||
|
<span class="property-type">string</span>
|
||||||
|
</dt>
|
||||||
|
<dd> The room identifier to leave: for example, <code>!h8zld9j31:example.com</code>.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3>Outputs</h3>
|
||||||
|
<ol class="node-ports">
|
||||||
|
<li>Success
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.payload <span class="property-type">object</span></dt>
|
||||||
|
<dd>Returns the same message that was received</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li>Error
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.error <span class="property-type">string</span></dt>
|
||||||
|
<dd>the error that occurred.</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
</script>
|
54
src/matrix-leave-room.js
Normal file
54
src/matrix-leave-room.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
module.exports = function(RED) {
|
||||||
|
function MatrixLeaveRoom(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
|
let node = this;
|
||||||
|
|
||||||
|
this.name = n.name;
|
||||||
|
this.server = RED.nodes.getNode(n.server);
|
||||||
|
this.roomId = n.roomId;
|
||||||
|
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
|
||||||
|
if (!node.server) {
|
||||||
|
node.error("No configuration node");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.server.on("disconnected", function(){
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.server.on("connected", function() {
|
||||||
|
node.status({ fill: "green", shape: "ring", text: "connected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on('input', function(msg) {
|
||||||
|
if (! node.server || ! node.server.matrixClient) {
|
||||||
|
node.error("No matrix server selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!msg.topic) {
|
||||||
|
node.error('No room provided in msg.topic');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!node.server.isConnected()) {
|
||||||
|
node.error("Matrix server connection is currently closed");
|
||||||
|
node.send([null, msg]);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
node.log("Leaving room " + msg.topic);
|
||||||
|
node.server.matrixClient.leave(msg.topic);
|
||||||
|
node.send([msg, null]);
|
||||||
|
} catch(e) {
|
||||||
|
node.error("Failed to leave room " + msg.topic + ": " + e);
|
||||||
|
msg.payload = e;
|
||||||
|
node.send([null, msg]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("matrix-leave-room", MatrixLeaveRoom);
|
||||||
|
}
|
@ -17,6 +17,7 @@
|
|||||||
acceptFiles: {"value": true},
|
acceptFiles: {"value": true},
|
||||||
acceptAudio: {"value": true},
|
acceptAudio: {"value": true},
|
||||||
acceptImages: {"value": true},
|
acceptImages: {"value": true},
|
||||||
|
acceptVideos: {"value": true},
|
||||||
acceptLocations: {"value": true},
|
acceptLocations: {"value": true},
|
||||||
},
|
},
|
||||||
label: function() {
|
label: function() {
|
||||||
@ -114,6 +115,16 @@
|
|||||||
Accept images <code style="text-transform: none;">m.image</code>
|
Accept images <code style="text-transform: none;">m.image</code>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="node-input-acceptVideos"
|
||||||
|
style="width: auto; margin-left: 125px; vertical-align: top"
|
||||||
|
/>
|
||||||
|
<label for="node-input-acceptVideos" style="width: auto">
|
||||||
|
Accept videos <code style="text-transform: none;">m.video</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@ -13,6 +13,7 @@ module.exports = function(RED) {
|
|||||||
this.acceptFiles = n.acceptFiles;
|
this.acceptFiles = n.acceptFiles;
|
||||||
this.acceptAudio = n.acceptAudio;
|
this.acceptAudio = n.acceptAudio;
|
||||||
this.acceptImages = n.acceptImages;
|
this.acceptImages = n.acceptImages;
|
||||||
|
this.acceptVideos = n.acceptVideos;
|
||||||
this.acceptLocations = n.acceptLocations;
|
this.acceptLocations = n.acceptLocations;
|
||||||
this.roomId = n.roomId;
|
this.roomId = n.roomId;
|
||||||
this.roomIds = this.roomId ? this.roomId.split(',') : [];
|
this.roomIds = this.roomId ? this.roomId.split(',') : [];
|
||||||
@ -111,6 +112,23 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'm.video':
|
||||||
|
if(!node.acceptVideos) return;
|
||||||
|
msg.filename = msg.content.filename || msg.content.body;
|
||||||
|
if(msg.encrypted) {
|
||||||
|
msg.url = node.server.matrixClient.mxcUrlToHttp(msg.content.file.url);
|
||||||
|
msg.mxc_url = msg.content.file.url;
|
||||||
|
msg.thumbnail_url = node.server.matrixClient.mxcUrlToHttp(msg.content.info.thumbnail_file.url);
|
||||||
|
msg.thumbnail_mxc_url = msg.content.info.thumbnail_file.url;
|
||||||
|
} else {
|
||||||
|
msg.url = node.server.matrixClient.mxcUrlToHttp(msg.content.url);
|
||||||
|
msg.mxc_url = msg.content.url;
|
||||||
|
msg.thumbnail_url = node.server.matrixClient.mxcUrlToHttp(msg.content.info.thumbnail_url);
|
||||||
|
msg.thumbnail_mxc_url = msg.content.info.thumbnail_url;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'm.location':
|
case 'm.location':
|
||||||
if(!node.acceptLocations) return;
|
if(!node.acceptLocations) return;
|
||||||
msg.geo_uri = msg.content.geo_uri;
|
msg.geo_uri = msg.content.geo_uri;
|
||||||
|
80
src/matrix-room-invite.html
Normal file
80
src/matrix-room-invite.html
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('matrix-room-invite', {
|
||||||
|
category: 'matrix',
|
||||||
|
color: '#00b7ca',
|
||||||
|
icon: "matrix.png",
|
||||||
|
outputLabels: ["success", "error"],
|
||||||
|
inputs: 0,
|
||||||
|
outputs: 1,
|
||||||
|
defaults: {
|
||||||
|
name: { value: null },
|
||||||
|
server: { value: "", type: "matrix-server-config" },
|
||||||
|
roomId: { value: null },
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.name || "Room Invite";
|
||||||
|
},
|
||||||
|
paletteLabel: 'Room Invite'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-template-name="matrix-room-invite">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-server"><i class="fa fa-user"></i> Matrix Server Config</label>
|
||||||
|
<input type="text" id="node-input-server">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-help-name="matrix-room-invite">
|
||||||
|
<h3>Details</h3>
|
||||||
|
<p>
|
||||||
|
This node receives room invites.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Outputs</h3>
|
||||||
|
<ol class="node-ports">
|
||||||
|
<li>Success
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.type <span class="property-type">string</span></dt>
|
||||||
|
<dd>Always <code>m.room.member</code></dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.userId <span class="property-type">string</span></dt>
|
||||||
|
<dd>ID of the user the invite is from</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.topic <span class="property-type">string</span></dt>
|
||||||
|
<dd>The room identifier for the invite: for example, <code>!h8zld9j31:example.com</code>.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.topicName <span class="property-type">string</span></dt>
|
||||||
|
<dd>The invited room name.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.event <span class="property-type">object</span></dt>
|
||||||
|
<dd>The event object for this invite to get extra details.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.eventId <span class="property-type">object</span></dt>
|
||||||
|
<dd>The ID of the event for this invite.</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li>Error
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.error <span class="property-type">string</span></dt>
|
||||||
|
<dd>the error that occurred.</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
</script>
|
31
src/matrix-room-invite.js
Normal file
31
src/matrix-room-invite.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
module.exports = function(RED) {
|
||||||
|
function MatrixRoomInvite(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
|
let node = this;
|
||||||
|
|
||||||
|
this.name = n.name;
|
||||||
|
this.server = RED.nodes.getNode(n.server);
|
||||||
|
this.roomId = n.roomId;
|
||||||
|
|
||||||
|
if(!this.server) {
|
||||||
|
node.error('Server must be configured on the node.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
|
||||||
|
node.server.on("disconnected", function(){
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.server.on("connected", function() {
|
||||||
|
node.status({ fill: "green", shape: "ring", text: "connected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.server.on("Room.invite", async function(msg) {
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("matrix-room-invite", MatrixRoomInvite);
|
||||||
|
}
|
@ -162,7 +162,7 @@
|
|||||||
$("#matrix-access-token-loader").show();
|
$("#matrix-access-token-loader").show();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '/matrix-chat/login',
|
url: 'matrix-chat/login',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
data: {
|
data: {
|
||||||
'userId': userId,
|
'userId': userId,
|
||||||
|
@ -4,9 +4,30 @@ const sdk = require("matrix-js-sdk");
|
|||||||
const { resolve } = require('path');
|
const { resolve } = require('path');
|
||||||
const { LocalStorage } = require('node-localstorage');
|
const { LocalStorage } = require('node-localstorage');
|
||||||
const { LocalStorageCryptoStore } = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
|
const { LocalStorageCryptoStore } = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
|
||||||
const {RoomEvent, RoomMemberEvent, HttpApiEvent, ClientEvent} = require("matrix-js-sdk");
|
const {RoomEvent, RoomMemberEvent, HttpApiEvent, ClientEvent, MemoryStore} = require("matrix-js-sdk");
|
||||||
|
const request = require("request");
|
||||||
|
require("abort-controller/polyfill"); // polyfill abort-controller if we don't have it
|
||||||
|
if (!globalThis.fetch) {
|
||||||
|
// polyfill fetch if we don't have it
|
||||||
|
if (!globalThis.fetch) {
|
||||||
|
import('node-fetch').then(({ default: fetch, Headers, Request, Response }) => {
|
||||||
|
Object.assign(globalThis, { fetch, Headers, Request, Response })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = function(RED) {
|
module.exports = function(RED) {
|
||||||
|
// disable logging if set to "off"
|
||||||
|
let loggingSettings = RED.settings.get('logging');
|
||||||
|
if(
|
||||||
|
typeof loggingSettings.console !== 'undefined' &&
|
||||||
|
typeof loggingSettings.console.level !== 'undefined' &&
|
||||||
|
['info','debug','trace'].indexOf(loggingSettings.console.level.toLowerCase()) >= 0
|
||||||
|
) {
|
||||||
|
const { logger } = require('matrix-js-sdk/lib/logger');
|
||||||
|
logger.disableAll();
|
||||||
|
}
|
||||||
|
|
||||||
function MatrixFolderNameFromUserId(name) {
|
function MatrixFolderNameFromUserId(name) {
|
||||||
return name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
|
return name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
|
||||||
}
|
}
|
||||||
@ -116,10 +137,13 @@ module.exports = function(RED) {
|
|||||||
node.matrixClient = sdk.createClient({
|
node.matrixClient = sdk.createClient({
|
||||||
baseUrl: this.url,
|
baseUrl: this.url,
|
||||||
accessToken: this.credentials.accessToken,
|
accessToken: this.credentials.accessToken,
|
||||||
sessionStore: new sdk.WebStorageSessionStore(localStorage),
|
|
||||||
cryptoStore: new LocalStorageCryptoStore(localStorage),
|
cryptoStore: new LocalStorageCryptoStore(localStorage),
|
||||||
|
store: new MemoryStore({
|
||||||
|
localStorage: localStorage,
|
||||||
|
}),
|
||||||
userId: this.userId,
|
userId: this.userId,
|
||||||
deviceId: (this.deviceId || getStoredDeviceId(localStorage)) || undefined,
|
deviceId: (this.deviceId || getStoredDeviceId(localStorage)) || undefined,
|
||||||
|
request
|
||||||
// verificationMethods: ["m.sas.v1"]
|
// verificationMethods: ["m.sas.v1"]
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -230,16 +254,30 @@ module.exports = function(RED) {
|
|||||||
// handle auto-joining rooms
|
// handle auto-joining rooms
|
||||||
|
|
||||||
node.matrixClient.on(RoomMemberEvent.Membership, async function(event, member) {
|
node.matrixClient.on(RoomMemberEvent.Membership, async function(event, member) {
|
||||||
|
if(node.initializedAt > event.getDate()) {
|
||||||
|
return; // skip events that occurred before our client initialized
|
||||||
|
}
|
||||||
|
|
||||||
if (member.membership === "invite" && member.userId === node.userId) {
|
if (member.membership === "invite" && member.userId === node.userId) {
|
||||||
|
node.log("Got invite to join room " + member.roomId);
|
||||||
|
console.log(event);
|
||||||
if(node.autoAcceptRoomInvites) {
|
if(node.autoAcceptRoomInvites) {
|
||||||
node.matrixClient.joinRoom(member.roomId).then(function() {
|
node.matrixClient.joinRoom(member.roomId).then(function() {
|
||||||
node.log("Automatically accepted invitation to join room " + member.roomId);
|
node.log("Automatically accepted invitation to join room " + member.roomId);
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
node.warn("Cannot join room (could be from being kicked/banned) " + member.roomId + ": " + e);
|
node.warn("Cannot join room (could be from being kicked/banned) " + member.roomId + ": " + e);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
node.log("Got invite to join room " + member.roomId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let room = node.matrixClient.getRoom(event.getRoomId());
|
||||||
|
node.emit("Room.invite", {
|
||||||
|
type : 'm.room.member',
|
||||||
|
userId : event.getSender(),
|
||||||
|
topic : event.getRoomId(),
|
||||||
|
topicName : (room ? room.name : null) || null,
|
||||||
|
event : event,
|
||||||
|
eventId : event.getId(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -411,7 +449,8 @@ module.exports = function(RED) {
|
|||||||
const matrixClient = sdk.createClient({
|
const matrixClient = sdk.createClient({
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
localTimeoutMs: '30000'
|
localTimeoutMs: '30000',
|
||||||
|
request
|
||||||
});
|
});
|
||||||
|
|
||||||
matrixClient.login(
|
matrixClient.login(
|
||||||
@ -442,7 +481,7 @@ module.exports = function(RED) {
|
|||||||
let oldStorageDir = './matrix-local-storage',
|
let oldStorageDir = './matrix-local-storage',
|
||||||
oldStorageDir2 = './matrix-client-storage';
|
oldStorageDir2 = './matrix-client-storage';
|
||||||
|
|
||||||
// if the old storage location exists lets move it to it's new location
|
// if the old storage location exists lets move it to the new location
|
||||||
if(fs.pathExistsSync(oldStorageDir)){
|
if(fs.pathExistsSync(oldStorageDir)){
|
||||||
RED.nodes.eachNode(function(n){
|
RED.nodes.eachNode(function(n){
|
||||||
try {
|
try {
|
||||||
@ -455,7 +494,7 @@ module.exports = function(RED) {
|
|||||||
fs.copySync(oldStorageDir, dir);
|
fs.copySync(oldStorageDir, dir);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
node.error(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
node.server.matrixClient.http
|
node.server.matrixClient.http
|
||||||
.authedRequest(
|
.authedRequest(
|
||||||
undefined,
|
|
||||||
'PUT',
|
'PUT',
|
||||||
node.encodeUri(
|
node.encodeUri(
|
||||||
"/_synapse/admin/v2/users/$userId",
|
"/_synapse/admin/v2/users/$userId",
|
||||||
|
@ -56,7 +56,6 @@ module.exports = function(RED) {
|
|||||||
);
|
);
|
||||||
node.server.matrixClient.http
|
node.server.matrixClient.http
|
||||||
.authedRequest(
|
.authedRequest(
|
||||||
undefined,
|
|
||||||
'POST',
|
'POST',
|
||||||
path,
|
path,
|
||||||
undefined,
|
undefined,
|
||||||
|
@ -60,7 +60,6 @@ module.exports = function(RED) {
|
|||||||
// we need the status code, so set onlydata to false for this request
|
// we need the status code, so set onlydata to false for this request
|
||||||
node.server.matrixClient.http
|
node.server.matrixClient.http
|
||||||
.authedRequest(
|
.authedRequest(
|
||||||
undefined,
|
|
||||||
'POST',
|
'POST',
|
||||||
node.encodeUri(
|
node.encodeUri(
|
||||||
"/_synapse/admin/v1/join/$room_id_or_alias",
|
"/_synapse/admin/v1/join/$room_id_or_alias",
|
||||||
|
@ -48,7 +48,6 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
node.server.matrixClient.http
|
node.server.matrixClient.http
|
||||||
.authedRequest(
|
.authedRequest(
|
||||||
undefined,
|
|
||||||
'GET',
|
'GET',
|
||||||
"/_synapse/admin/v2/users",
|
"/_synapse/admin/v2/users",
|
||||||
queryParams,
|
queryParams,
|
||||||
|
@ -53,7 +53,6 @@ module.exports = function(RED) {
|
|||||||
// we need the status code, so set onlydata to false for this request
|
// we need the status code, so set onlydata to false for this request
|
||||||
node.server.matrixClient.http
|
node.server.matrixClient.http
|
||||||
.authedRequest(
|
.authedRequest(
|
||||||
undefined,
|
|
||||||
'GET',
|
'GET',
|
||||||
node.encodeUri(
|
node.encodeUri(
|
||||||
"/_matrix/client/r0/admin/whois/$userId",
|
"/_matrix/client/r0/admin/whois/$userId",
|
||||||
|
Loading…
Reference in New Issue
Block a user