From 18596961226edd5fe2c7cdac66ffebde850dafd0 Mon Sep 17 00:00:00 2001 From: Skylar Sadlier Date: Sun, 22 Oct 2023 00:29:12 -0600 Subject: [PATCH] - #97 added option to fetch state event from local storage and fallback to server if necessary (allows for faster lookups and gives the full event object with information about when/who created it, etc) - #97 remove num, bool, bin, and data from being options you can set to a state event (currently only objects and sometimes strings are allowed) - Updated Leave Room node so it deletes the room from local storage - Updated server config node so it deletes the matrix client from storage during shutdown (possibly solution to #94) --- src/matrix-leave-room.js | 1 + src/matrix-room-state-events.html | 30 +++++++++++++++++---- src/matrix-room-state-events.js | 44 +++++++++++++++++++------------ src/matrix-server-config.js | 7 +++++ 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/matrix-leave-room.js b/src/matrix-leave-room.js index daebb33..b46f8d7 100644 --- a/src/matrix-leave-room.js +++ b/src/matrix-leave-room.js @@ -44,6 +44,7 @@ module.exports = function(RED) { try { node.log("Leaving room " + msg.topic); node.server.matrixClient.leave(msg.topic); + node.server.matrixClient.store.removeRoom(msg.topic); node.send([msg, null]); } catch(e) { node.error("Failed to leave room " + msg.topic + ": " + e, msg); diff --git a/src/matrix-room-state-events.html b/src/matrix-room-state-events.html index 26c7be1..08395dc 100644 --- a/src/matrix-room-state-events.html +++ b/src/matrix-room-state-events.html @@ -69,7 +69,7 @@
dynamic string|object
-
You configure what room state events to output in the node configuration. m.room.name, m.room.avatar, and m.room.guest_access will come back as strings otherwise you will get the full content object of the event (find this by referencing the Matrix Client-Server docs)
+
You configure what room state events to output in the node configuration. m.room.name, m.room.avatar, and m.room.guest_access will come back as strings otherwise you will get the full content object of the event (find this by referencing the Matrix Client-Server docs). Additionally there is a setting when configuring a getter called "Fetch from local storage" that if enabled will search the local storage for the room and try to fetch the state event that way and fallback to hitting the server if that isn't possible.
@@ -156,15 +156,17 @@ .appendTo(row2_1) .typedInput({ default: defaultType || (type === 'set' ? 'str' : 'msg'), - types: (type === 'set' ? ['msg','flow','global','str','num','bool','json','bin','date','jsonata'] : ['msg', 'flow', 'global']) + types: (type === 'set' ? ['msg','flow','global','str','json','jsonata'] : ['msg', 'flow', 'global']) }); - var dcLabel = $('').appendTo(row2_2); + var lsLabel = $('').appendTo(row2_2); + var localStorageEl = $('').appendTo(lsLabel); + $('').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]; + return [propValInput, localStorageEl]; } $('#node-input-rule-container').css('min-height','150px').css('min-width','450px').editableList({ @@ -259,6 +261,7 @@ .appendTo(row4); let propertyValue = null; + let localStorageEl = null; let fromValue = null; let toValue = null; @@ -277,12 +280,18 @@ 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','num','bool','json','bin','date','jsonata','env'] : ['msg', 'flow', 'global'])); + 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(); }); @@ -292,7 +301,14 @@ 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.show(); + } else { + localStorageEl.hide(); + } } selectField.change(); container[0].appendChild(fragment); @@ -319,6 +335,10 @@ 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); }); }, diff --git a/src/matrix-room-state-events.js b/src/matrix-room-state-events.js index e8f2a1f..bd6025c 100644 --- a/src/matrix-room-state-events.js +++ b/src/matrix-room-state-events.js @@ -226,23 +226,33 @@ module.exports = function(RED) { value = cachedGetters[rule.p]; } else { try { - // we may want to fetch from local storage in the future, this is how to do that - // const room = this.getRoom(roomId); - // const ev = room.currentState.getStateEvents(EventType.RoomEncryption, ""); - value = await node.server.matrixClient.getStateEvent(msg.topic, rule.p, ""); - switch(rule.p) { - case "m.room.name": - value = value?.name - break; - case "m.room.topic": - value = value?.topic - break; - case "m.room.avatar": - value = value?.url - break; - case "m.room.guest_access": - value = value?.guest_access; - break; + if(rule.ls) { + // we opted to lookup from local storage, will fallback to server if necessary + let room = node.server.matrixClient.getRoom(msg.topic); + if(room) { + value = await room.getLiveTimeline().getState("f").getStateEvents(rule.p, ""); + } + } + if(!value) { + // fetch the latest state event by type from server + value = await node.server.matrixClient.getStateEvent(msg.topic, rule.p, ""); + if(value) { + // normalize some simpler events for easier access + switch(rule.p) { + case "m.room.name": + value = value?.name + break; + case "m.room.topic": + value = value?.topic + break; + case "m.room.avatar": + value = value?.url + break; + case "m.room.guest_access": + value = value?.guest_access; + break; + } + } } setToValue(value, rule); } catch(e) { diff --git a/src/matrix-server-config.js b/src/matrix-server-config.js index 920f3af..59c9e2a 100644 --- a/src/matrix-server-config.js +++ b/src/matrix-server-config.js @@ -174,6 +174,13 @@ module.exports = function(RED) { node.on('close', function(done) { stopClient(); + if(node.globalAccess) { + try { + node.context().global.delete('matrixClient["'+node.userId+'"]'); + } catch(e){ + node.error(e.message, {}); + } + } done(); });