diff --git a/package-lock.json b/package-lock.json index bf857a5..432c3f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "ansi-colors": "^4.1.3", "better-sqlite3": "^12.2.0", "chunk-text": "^2.0.1", - "cloudstorm": "^0.14.0", + "cloudstorm": "^0.15.2", "discord-api-types": "^0.38.36", "domino": "^2.1.6", "enquirer": "^2.4.1", @@ -35,7 +35,7 @@ "lru-cache": "^11.0.2", "prettier-bytes": "^1.0.4", "sharp": "^0.34.5", - "snowtransfer": "^0.14.2", + "snowtransfer": "^0.17.0", "stream-mime-type": "^1.0.2", "try-to-catch": "^3.0.1", "uqr": "^0.1.2", @@ -1552,30 +1552,18 @@ } }, "node_modules/cloudstorm": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.14.1.tgz", - "integrity": "sha512-x95WCKg818E1rE1Ru45NPD3RoIq0pg3WxwvF0GE7Eq07pAeLcjSRqM1lUmbmfjdOqZrWdSRYA1NETVZ8QhVrIA==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.15.2.tgz", + "integrity": "sha512-5y7E0uI39R3d7c+AWksqAQAlZlpx+qNjxjQfNIem2hh68s6QRmOFHTKu34I7pBE6JonpZf8AmoMYArY/4lLVmg==", "license": "MIT", "dependencies": { - "discord-api-types": "^0.38.21", - "snowtransfer": "^0.15.0" + "discord-api-types": "^0.38.37", + "snowtransfer": "^0.17.0" }, "engines": { "node": ">=22.0.0" } }, - "node_modules/cloudstorm/node_modules/snowtransfer": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.15.0.tgz", - "integrity": "sha512-kEDGKtFiH5nSkHsDZonEUuDx99lUasJoZ7AGrgvE8HzVG59vjvqc//C+pjWj4DuJqTj4Q+Z1L/M/MYNim8F2VA==", - "license": "MIT", - "dependencies": { - "discord-api-types": "^0.38.21" - }, - "engines": { - "node": ">=16.15.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1711,9 +1699,9 @@ } }, "node_modules/discord-api-types": { - "version": "0.38.36", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.36.tgz", - "integrity": "sha512-qrbUbjjwtyeBg5HsAlm1C859epfOyiLjPqAOzkdWlCNsZCWJrertnETF/NwM8H+waMFU58xGSc5eXUfXah+WTQ==", + "version": "0.38.37", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.37.tgz", + "integrity": "sha512-Cv47jzY1jkGkh5sv0bfHYqGgKOWO1peOrGMkDFM4UmaGMOTgOW8QSexhvixa9sVOiz8MnVOBryWYyw/CEVhj7w==", "license": "MIT", "workspaces": [ "scripts/actions/documentation" @@ -1971,9 +1959,9 @@ } }, "node_modules/h3": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.4.tgz", - "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.5.tgz", + "integrity": "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==", "license": "MIT", "dependencies": { "cookie-es": "^1.2.2", @@ -1981,9 +1969,9 @@ "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", - "node-mock-http": "^1.0.2", + "node-mock-http": "^1.0.4", "radix3": "^1.1.2", - "ufo": "^1.6.1", + "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, @@ -2321,9 +2309,9 @@ } }, "node_modules/node-mock-http": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.2.tgz", - "integrity": "sha512-zWaamgDUdo9SSLw47we78+zYw/bDr5gH8pH7oRRs8V3KmBtu8GLgGIbV2p/gRPd3LWpEOpjQj7X1FOU3VFMJ8g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", + "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", "license": "MIT" }, "node_modules/object-assign": { @@ -2821,15 +2809,15 @@ } }, "node_modules/snowtransfer": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.14.2.tgz", - "integrity": "sha512-Fi8OdRmaIgeCj58oVej+tQAoY2I+Xp/6PAYV8X93jE/2E6Anc87SbTbDV6WZXCnuzTQz3gty8JOGz02qI7Qs9A==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.17.0.tgz", + "integrity": "sha512-H6Avpsco+HlVIkN+MbX34Q7+9g9Wci0wZQwGsvfw20VqEb7jnnk73iUcWytNMYtKZ72Ud58n6cFnQ3apTEamxw==", "license": "MIT", "dependencies": { - "discord-api-types": "^0.38.8" + "discord-api-types": "^0.38.37" }, "engines": { - "node": ">=16.15.0" + "node": ">=22.0.0" } }, "node_modules/source-map": { @@ -3244,9 +3232,9 @@ } }, "node_modules/ufo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", "license": "MIT" }, "node_modules/uncrypto": { diff --git a/package.json b/package.json index 64e6f77..4d0c43a 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "ansi-colors": "^4.1.3", "better-sqlite3": "^12.2.0", "chunk-text": "^2.0.1", - "cloudstorm": "^0.14.0", + "cloudstorm": "^0.15.2", "discord-api-types": "^0.38.36", "domino": "^2.1.6", "enquirer": "^2.4.1", @@ -44,7 +44,7 @@ "lru-cache": "^11.0.2", "prettier-bytes": "^1.0.4", "sharp": "^0.34.5", - "snowtransfer": "^0.14.2", + "snowtransfer": "^0.17.0", "stream-mime-type": "^1.0.2", "try-to-catch": "^3.0.1", "uqr": "^0.1.2", @@ -64,7 +64,6 @@ "scripts": { "start": "node --enable-source-maps start.js", "setup": "node --enable-source-maps scripts/setup.js", - "build": "mkdir -p dist/out-of-your-element && cp -R src dist/out-of-your-element && cp -R docs dist/out-of-your-element && npx tsdown", "addbot": "node addbot.js", "test": "cross-env FORCE_COLOR=true supertape --no-check-assertions-count --format tap --no-worker test/test.js | tap-dot", "test-slow": "cross-env FORCE_COLOR=true supertape --no-check-assertions-count --format tap --no-worker test/test.js -- --slow | tap-dot", diff --git a/src/d2m/actions/update-pins.js b/src/d2m/actions/update-pins.js index 15febaa..56c9642 100644 --- a/src/d2m/actions/update-pins.js +++ b/src/d2m/actions/update-pins.js @@ -34,7 +34,7 @@ async function updatePins(channelID, roomID, convertedTimestamp) { throw e } - const kstate = await ks.roomToKState(roomID) + const kstate = await ks.roomToKState(roomID, [["m.room.pinned_events", ""]]) const pinned = pinsToList.pinsToList(discordPins, kstate) const diff = ks.diffKState(kstate, {"m.room.pinned_events/": {pinned}}) diff --git a/src/d2m/converters/pins-to-list.js b/src/d2m/converters/pins-to-list.js index 3e890ea..5a33c7c 100644 --- a/src/d2m/converters/pins-to-list.js +++ b/src/d2m/converters/pins-to-list.js @@ -3,10 +3,11 @@ const {select} = require("../../passthrough") /** - * @param {import("discord-api-types/v10").RESTGetAPIChannelPinsResult} pins + * @param {import("discord-api-types/v10").RESTGetAPIChannelMessagesPinsResult} pins * @param {{"m.room.pinned_events/"?: {pinned?: string[]}}} kstate */ function pinsToList(pins, kstate) { + /** Most recent last. */ let alreadyPinned = kstate["m.room.pinned_events/"]?.pinned || [] // If any of the already pinned messages are bridged messages then remove them from the already pinned list. @@ -15,13 +16,13 @@ function pinsToList(pins, kstate) { // * Matrix-only unbridged messages that are pinned will remain pinned. alreadyPinned = alreadyPinned.filter(event_id => { const messageID = select("event_message", "message_id", {event_id}).pluck().get() - return !messageID || pins.find(m => m.id === messageID) // if it is bridged then remove it from the filter + return !messageID || pins.items.find(m => m.message.id === messageID) // if it is bridged then remove it from the filter }) /** @type {string[]} */ const result = [] - for (const message of pins) { - const eventID = select("event_message", "event_id", {message_id: message.id, part: 0}).pluck().get() + for (const pin of pins.items) { + const eventID = select("event_message", "event_id", {message_id: pin.message.id, part: 0}).pluck().get() if (eventID && !alreadyPinned.includes(eventID)) result.push(eventID) } result.reverse() diff --git a/src/d2m/converters/pins-to-list.test.js b/src/d2m/converters/pins-to-list.test.js index d0657cb..571735e 100644 --- a/src/d2m/converters/pins-to-list.test.js +++ b/src/d2m/converters/pins-to-list.test.js @@ -1,6 +1,7 @@ const {test} = require("supertape") const data = require("../../../test/data") const {pinsToList} = require("./pins-to-list") +const mixin = require("@cloudrac3r/mixin-deep") test("pins2list: converts known IDs, ignores unknown IDs", t => { const result = pinsToList(data.pins.faked, {}) @@ -46,7 +47,9 @@ test("pins2list: already pinned unknown items are not moved", t => { }) test("pins2list: bridged messages can be unpinned", t => { - const result = pinsToList(data.pins.faked.slice(0, -2), { + const shortPins = mixin({}, data.pins.faked) + shortPins.items = shortPins.items.slice(0, -2) + const result = pinsToList(shortPins, { "m.room.pinned_events/": { pinned: [ "$mtR8cJqM4fKno1bVsm8F4wUVqSntt2sq6jav1lyavuA", diff --git a/src/matrix/kstate.js b/src/matrix/kstate.js index 37eed39..c901ce1 100644 --- a/src/matrix/kstate.js +++ b/src/matrix/kstate.js @@ -140,10 +140,20 @@ function diffKState(actual, target) { /** * Async because it gets all room state from the homeserver. * @param {string} roomID + * @param {[type: string, key: string][]} [limitToEvents] */ -async function roomToKState(roomID) { - const root = await api.getAllState(roomID) - return stateToKState(root) +async function roomToKState(roomID, limitToEvents) { + if (!limitToEvents) { + const root = await api.getAllState(roomID) + return stateToKState(root) + } else { + const root = [] + await Promise.all(limitToEvents.map(async ([type, key]) => { + const outer = await api.getStateEventOuter(roomID, type, key) + root.push(outer) + })) + return stateToKState(root) + } } /** diff --git a/test/data.js b/test/data.js index e80b436..0942a87 100644 --- a/test/data.js +++ b/test/data.js @@ -1256,12 +1256,14 @@ module.exports = { } }, pins: { - faked: [ - {id: "1126786462646550579"}, - {id: "1141501302736695316"}, - {id: "1106366167788044450"}, - {id: "1115688611186193400"} - ] + faked: { + items: [ + {message: {id: "1126786462646550579"}}, + {message: {id: "1141501302736695316"}}, + {message: {id: "1106366167788044450"}}, + {message: {id: "1115688611186193400"}} + ] + } }, message: { // Display order is text content, attachments, then stickers