Sync pins back from Matrix to Discord
This commit is contained in:
parent
4c62124cee
commit
06b6a63ee3
6 changed files with 87 additions and 0 deletions
25
src/m2d/actions/update-pins.js
Normal file
25
src/m2d/actions/update-pins.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const {sync, from, discord} = require("../../passthrough")
|
||||||
|
|
||||||
|
/** @type {import("../converters/diff-pins")} */
|
||||||
|
const diffPins = sync.require("../converters/diff-pins")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} pins
|
||||||
|
* @param {string[]} prev
|
||||||
|
*/
|
||||||
|
async function updatePins(pins, prev) {
|
||||||
|
const diff = diffPins.diffPins(pins, prev)
|
||||||
|
for (const [event_id, added] of diff) {
|
||||||
|
const row = from("event_message").join("message_channel", "message_id").where({event_id}).select("channel_id", "message_id").get()
|
||||||
|
if (!row) continue
|
||||||
|
if (added) {
|
||||||
|
discord.snow.channel.addChannelPinnedMessage(row.channel_id, row.message_id, "Message pinned on Matrix")
|
||||||
|
} else {
|
||||||
|
discord.snow.channel.removeChannelPinnedMessage(row.channel_id, row.message_id, "Message unpinned on Matrix")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.updatePins = updatePins
|
17
src/m2d/converters/diff-pins.js
Normal file
17
src/m2d/converters/diff-pins.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} pins
|
||||||
|
* @param {string[]} prev
|
||||||
|
* @returns {[string, boolean][]}
|
||||||
|
*/
|
||||||
|
function diffPins(pins, prev) {
|
||||||
|
/** @type {[string, boolean][]} */
|
||||||
|
const result = []
|
||||||
|
return result.concat(
|
||||||
|
prev.filter(id => !pins.includes(id)).map(id => [id, false]), // removed
|
||||||
|
pins.filter(id => !prev.includes(id)).map(id => [id, true]) // added
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.diffPins = diffPins
|
11
src/m2d/converters/diff-pins.test.js
Normal file
11
src/m2d/converters/diff-pins.test.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const {test} = require("supertape")
|
||||||
|
const diffPins = require("./diff-pins")
|
||||||
|
|
||||||
|
test("diff pins: diff is as expected", t => {
|
||||||
|
t.deepEqual(
|
||||||
|
diffPins.diffPins(["same", "new"], ["same", "old"]),
|
||||||
|
[["old", false], ["new", true]]
|
||||||
|
)
|
||||||
|
})
|
|
@ -14,6 +14,8 @@ const sendEvent = sync.require("./actions/send-event")
|
||||||
const addReaction = sync.require("./actions/add-reaction")
|
const addReaction = sync.require("./actions/add-reaction")
|
||||||
/** @type {import("./actions/redact")} */
|
/** @type {import("./actions/redact")} */
|
||||||
const redact = sync.require("./actions/redact")
|
const redact = sync.require("./actions/redact")
|
||||||
|
/** @type {import("./actions/update-pins")}) */
|
||||||
|
const updatePins = sync.require("./actions/update-pins")
|
||||||
/** @type {import("../matrix/matrix-command-handler")} */
|
/** @type {import("../matrix/matrix-command-handler")} */
|
||||||
const matrixCommandHandler = sync.require("../matrix/matrix-command-handler")
|
const matrixCommandHandler = sync.require("../matrix/matrix-command-handler")
|
||||||
/** @type {import("./converters/utils")} */
|
/** @type {import("./converters/utils")} */
|
||||||
|
@ -159,6 +161,33 @@ async event => {
|
||||||
db.prepare("UPDATE channel_room SET nick = ? WHERE room_id = ?").run(name, event.room_id)
|
db.prepare("UPDATE channel_room SET nick = ? WHERE room_id = ?").run(name, event.room_id)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
sync.addTemporaryListener(as, "type:m.room.pinned_events", guard("m.room.pinned_events",
|
||||||
|
/**
|
||||||
|
* @param {Ty.Event.StateOuter<Ty.Event.M_Room_PinnedEvents>} event
|
||||||
|
*/
|
||||||
|
async event => {
|
||||||
|
if (event.state_key !== "") return
|
||||||
|
if (utils.eventSenderIsFromDiscord(event.sender)) return
|
||||||
|
const pins = event.content.pinned
|
||||||
|
if (!Array.isArray(pins)) return
|
||||||
|
let prev = event.unsigned?.prev_content?.pinned
|
||||||
|
if (!Array.isArray(prev)) {
|
||||||
|
if (pins.length === 1) {
|
||||||
|
/*
|
||||||
|
In edge cases, prev_content isn't guaranteed to be provided by the server.
|
||||||
|
If prev_content is missing, we can't diff. Better safe than sorry: we'd like to ignore the change rather than wiping the whole channel's pins on Discord.
|
||||||
|
However, that would mean if the first ever pin came from Matrix-side, it would be ignored, because there would be no prev_content (it's the first pinned event!)
|
||||||
|
So to handle that edge case, we assume that if there's exactly 1 entry in `pinned`, this is the first ever pin and it should go through.
|
||||||
|
*/
|
||||||
|
prev = []
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await updatePins.updatePins(pins, prev)
|
||||||
|
}))
|
||||||
|
|
||||||
sync.addTemporaryListener(as, "type:m.room.member", guard("m.room.member",
|
sync.addTemporaryListener(as, "type:m.room.member", guard("m.room.member",
|
||||||
/**
|
/**
|
||||||
* @param {Ty.Event.StateOuter<Ty.Event.M_Room_Member>} event
|
* @param {Ty.Event.StateOuter<Ty.Event.M_Room_Member>} event
|
||||||
|
|
4
src/types.d.ts
vendored
4
src/types.d.ts
vendored
|
@ -241,6 +241,10 @@ export namespace Event {
|
||||||
name?: string
|
name?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type M_Room_PinnedEvents = {
|
||||||
|
pinned: string[]
|
||||||
|
}
|
||||||
|
|
||||||
export type M_Power_Levels = {
|
export type M_Power_Levels = {
|
||||||
/** The level required to ban a user. Defaults to 50 if unspecified. */
|
/** The level required to ban a user. Defaults to 50 if unspecified. */
|
||||||
ban?: number,
|
ban?: number,
|
||||||
|
|
|
@ -139,6 +139,7 @@ file._actuallyUploadDiscordFileToMxc = function(url, res) { throw new Error(`Not
|
||||||
require("../src/d2m/converters/remove-reaction.test")
|
require("../src/d2m/converters/remove-reaction.test")
|
||||||
require("../src/d2m/converters/thread-to-announcement.test")
|
require("../src/d2m/converters/thread-to-announcement.test")
|
||||||
require("../src/d2m/converters/user-to-mxid.test")
|
require("../src/d2m/converters/user-to-mxid.test")
|
||||||
|
require("../src/m2d/converters/diff-pins.test")
|
||||||
require("../src/m2d/converters/event-to-message.test")
|
require("../src/m2d/converters/event-to-message.test")
|
||||||
require("../src/m2d/converters/utils.test")
|
require("../src/m2d/converters/utils.test")
|
||||||
require("../src/m2d/converters/emoji-sheet.test")
|
require("../src/m2d/converters/emoji-sheet.test")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue