d->m: Presence
This commit is contained in:
parent
f98c30cac3
commit
8ad0117fd2
6 changed files with 70 additions and 1 deletions
|
@ -36,6 +36,7 @@ Most features you'd expect in both directions, plus a little extra spice:
|
||||||
* Attachments
|
* Attachments
|
||||||
* Spoiler attachments
|
* Spoiler attachments
|
||||||
* Embeds
|
* Embeds
|
||||||
|
* Presence
|
||||||
* Guild-Space details syncing
|
* Guild-Space details syncing
|
||||||
* Channel-Room details syncing
|
* Channel-Room details syncing
|
||||||
* Custom emoji list 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: [
|
intents: [
|
||||||
"DIRECT_MESSAGES", "DIRECT_MESSAGE_REACTIONS", "DIRECT_MESSAGE_TYPING",
|
"DIRECT_MESSAGES", "DIRECT_MESSAGE_REACTIONS", "DIRECT_MESSAGE_TYPING",
|
||||||
"GUILDS", "GUILD_EMOJIS_AND_STICKERS", "GUILD_MESSAGES", "GUILD_MESSAGE_REACTIONS", "GUILD_MESSAGE_TYPING", "GUILD_WEBHOOKS",
|
"GUILDS", "GUILD_EMOJIS_AND_STICKERS", "GUILD_MESSAGES", "GUILD_MESSAGE_REACTIONS", "GUILD_MESSAGE_TYPING", "GUILD_WEBHOOKS",
|
||||||
"MESSAGE_CONTENT"
|
"MESSAGE_CONTENT", "GUILD_PRESENCES"
|
||||||
],
|
],
|
||||||
ws: {
|
ws: {
|
||||||
compress: false,
|
compress: false,
|
||||||
|
|
|
@ -196,6 +196,9 @@ const utils = {
|
||||||
|
|
||||||
} else if (message.t === "INTERACTION_CREATE") {
|
} else if (message.t === "INTERACTION_CREATE") {
|
||||||
await interactions.dispatchInteraction(message.d)
|
await interactions.dispatchInteraction(message.d)
|
||||||
|
|
||||||
|
} else if (message.t === "PRESENCE_UPDATE") {
|
||||||
|
eventDispatcher.onPresenceUpdate(message.d.user.id, message.d.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -33,6 +33,8 @@ const mxUtils = require("../m2d/converters/utils")
|
||||||
const speedbump = sync.require("./actions/speedbump")
|
const speedbump = sync.require("./actions/speedbump")
|
||||||
/** @type {import("./actions/retrigger")} */
|
/** @type {import("./actions/retrigger")} */
|
||||||
const retrigger = sync.require("./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
|
/** @type {any} */ // @ts-ignore bad types from semaphore
|
||||||
const Semaphore = require("@chriscdn/promise-semaphore")
|
const Semaphore = require("@chriscdn/promise-semaphore")
|
||||||
|
@ -369,5 +371,14 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
async onExpressionsUpdate(client, data) {
|
async onExpressionsUpdate(client, data) {
|
||||||
await createSpace.syncSpaceExpressions(data, false)
|
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)
|
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.path = path
|
||||||
module.exports.register = register
|
module.exports.register = register
|
||||||
module.exports.createRoom = createRoom
|
module.exports.createRoom = createRoom
|
||||||
|
@ -440,3 +448,4 @@ module.exports.ackEvent = ackEvent
|
||||||
module.exports.getAlias = getAlias
|
module.exports.getAlias = getAlias
|
||||||
module.exports.getAccountData = getAccountData
|
module.exports.getAccountData = getAccountData
|
||||||
module.exports.setAccountData = setAccountData
|
module.exports.setAccountData = setAccountData
|
||||||
|
module.exports.setPresence = setPresence
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue