d->m: Presence
This commit is contained in:
@@ -36,6 +36,7 @@ Most features you'd expect in both directions, plus a little extra spice:
|
||||
* Attachments
|
||||
* Spoiler attachments
|
||||
* Embeds
|
||||
* Presence
|
||||
* Guild-Space details syncing
|
||||
* Channel-Room details syncing
|
||||
* Custom emoji list syncing
|
||||
|
45
src/d2m/actions/set-presence.js
Normal file
45
src/d2m/actions/set-presence.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// @ts-check
|
||||
|
||||
const passthrough = require("../../passthrough")
|
||||
const {sync, select} = passthrough
|
||||
/** @type {import("../../matrix/api")} */
|
||||
const api = sync.require("../../matrix/api")
|
||||
|
||||
// Adding a debounce to all updates because events are issued multiple times, once for each guild.
|
||||
// Sometimes a status update is even issued twice in a row for the same user+guild, weird!
|
||||
const presenceDelay = 1500
|
||||
/** @type {Map<string, NodeJS.Timeout>} user ID -> cancelable timeout */
|
||||
const presenceDelayMap = new Map()
|
||||
|
||||
/**
|
||||
* @param {string} userID Discord user ID
|
||||
* @param {string} status status field from Discord's PRESENCE_UPDATE event
|
||||
*/
|
||||
function setPresence(userID, status) {
|
||||
// cancel existing timer if one is already set
|
||||
if (presenceDelayMap.has(userID)) {
|
||||
clearTimeout(presenceDelayMap.get(userID))
|
||||
}
|
||||
// new timer, which will run if nothing else comes in soon
|
||||
presenceDelayMap.set(userID, setTimeout(setPresenceCallback, presenceDelay, userID, status).unref())
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} user_id Discord user ID
|
||||
* @param {string} status status field from Discord's PRESENCE_UPDATE event
|
||||
*/
|
||||
function setPresenceCallback(user_id, status) {
|
||||
presenceDelayMap.delete(user_id)
|
||||
const mxid = select("sim", "mxid", {user_id}).pluck().get()
|
||||
if (!mxid) return
|
||||
const presence =
|
||||
( status === "online" ? "online"
|
||||
: status === "offline" ? "offline"
|
||||
: "unavailable") // idle, dnd, and anything else they dream up in the future
|
||||
api.setPresence(presence, mxid).catch(e => {
|
||||
console.error("d->m: Skipping presence update failure:")
|
||||
console.error(e)
|
||||
})
|
||||
}
|
||||
|
||||
module.exports.setPresence = setPresence
|
@@ -28,7 +28,7 @@ class DiscordClient {
|
||||
intents: [
|
||||
"DIRECT_MESSAGES", "DIRECT_MESSAGE_REACTIONS", "DIRECT_MESSAGE_TYPING",
|
||||
"GUILDS", "GUILD_EMOJIS_AND_STICKERS", "GUILD_MESSAGES", "GUILD_MESSAGE_REACTIONS", "GUILD_MESSAGE_TYPING", "GUILD_WEBHOOKS",
|
||||
"MESSAGE_CONTENT"
|
||||
"MESSAGE_CONTENT", "GUILD_PRESENCES"
|
||||
],
|
||||
ws: {
|
||||
compress: false,
|
||||
|
@@ -196,6 +196,9 @@ const utils = {
|
||||
|
||||
} else if (message.t === "INTERACTION_CREATE") {
|
||||
await interactions.dispatchInteraction(message.d)
|
||||
|
||||
} else if (message.t === "PRESENCE_UPDATE") {
|
||||
eventDispatcher.onPresenceUpdate(message.d.user.id, message.d.status)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
|
@@ -33,6 +33,8 @@ const mxUtils = require("../m2d/converters/utils")
|
||||
const speedbump = sync.require("./actions/speedbump")
|
||||
/** @type {import("./actions/retrigger")} */
|
||||
const retrigger = sync.require("./actions/retrigger")
|
||||
/** @type {import("./actions/set-presence")} */
|
||||
const setPresence = sync.require("./actions/set-presence")
|
||||
|
||||
/** @type {any} */ // @ts-ignore bad types from semaphore
|
||||
const Semaphore = require("@chriscdn/promise-semaphore")
|
||||
@@ -369,5 +371,14 @@ module.exports = {
|
||||
*/
|
||||
async onExpressionsUpdate(client, data) {
|
||||
await createSpace.syncSpaceExpressions(data, false)
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} userID
|
||||
* @param {string} [status]
|
||||
*/
|
||||
async onPresenceUpdate(userID, status) {
|
||||
if (!status) return
|
||||
setPresence.setPresence(userID, status)
|
||||
}
|
||||
}
|
||||
|
@@ -408,6 +408,14 @@ async function setAccountData(type, content, mxid) {
|
||||
await mreq.mreq("PUT", `/client/v3/user/${mxid}/account_data/${type}`, content)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {"online" | "offline" | "unavailable"} presence
|
||||
* @param {string} mxid
|
||||
*/
|
||||
async function setPresence(presence, mxid) {
|
||||
await mreq.mreq("PUT", path(`/client/v3/presence/${mxid}/status`, mxid), {presence})
|
||||
}
|
||||
|
||||
module.exports.path = path
|
||||
module.exports.register = register
|
||||
module.exports.createRoom = createRoom
|
||||
@@ -440,3 +448,4 @@ module.exports.ackEvent = ackEvent
|
||||
module.exports.getAlias = getAlias
|
||||
module.exports.getAccountData = getAccountData
|
||||
module.exports.setAccountData = setAccountData
|
||||
module.exports.setPresence = setPresence
|
||||
|
Reference in New Issue
Block a user