out-of-your-element/m2d/actions/channel-webhook.js

95 lines
3.3 KiB
JavaScript
Raw Normal View History

2023-06-30 03:15:34 +00:00
// @ts-check
const assert = require("assert").strict
2023-07-03 05:20:24 +00:00
const DiscordTypes = require("discord-api-types/v10")
const {Readable} = require("stream")
2023-06-30 03:15:34 +00:00
const passthrough = require("../../passthrough")
const {discord, db, select} = passthrough
2023-06-30 03:15:34 +00:00
/**
* Look in the database to find webhook credentials for a channel.
* (Note that the credentials may be invalid and need to be re-created if the webhook was interfered with from outside.)
* @param {string} channelID
* @param {boolean} forceCreate create a new webhook no matter what the database says about the state
* @returns id and token for a webhook for that channel
*/
async function ensureWebhook(channelID, forceCreate = false) {
if (!forceCreate) {
2023-10-05 23:31:10 +00:00
const row = select("webhook", ["webhook_id", "webhook_token"], {channel_id: channelID}).get()
2023-06-30 03:15:34 +00:00
if (row) {
return {
id: row.webhook_id,
token: row.webhook_token,
created: false
}
2023-06-30 03:15:34 +00:00
}
}
// If we got here, we need to create a new webhook.
const webhook = await discord.snow.webhook.createWebhook(channelID, {name: "Out Of Your Element: Matrix Bridge"})
assert(webhook.token)
db.prepare("REPLACE INTO webhook (channel_id, webhook_id, webhook_token) VALUES (?, ?, ?)").run(channelID, webhook.id, webhook.token)
return {
id: webhook.id,
token: webhook.token,
created: true
}
}
/**
* @param {string} channelID
* @param {(webhook: import("../../types").WebhookCreds) => Promise<T>} callback
* @returns Promise<T>
* @template T
*/
async function withWebhook(channelID, callback) {
const webhook = await ensureWebhook(channelID, false)
return callback(webhook).catch(e => {
// TODO: check if the error was webhook-related and if webhook.created === false, then: const webhook = ensureWebhook(channelID, true); return callback(webhook)
throw e
2023-06-30 03:15:34 +00:00
})
}
2023-07-03 05:20:24 +00:00
/**
* @param {string} channelID
* @param {DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {files?: {name: string, file: Buffer | Readable}[]}} data
2023-08-19 06:39:23 +00:00
* @param {string} [threadID]
2023-07-03 05:20:24 +00:00
*/
2023-08-19 06:39:23 +00:00
async function sendMessageWithWebhook(channelID, data, threadID) {
2023-08-21 09:04:41 +00:00
const result = await withWebhook(channelID, async webhook => {
return discord.snow.webhook.executeWebhook(webhook.id, webhook.token, data, {wait: true, thread_id: threadID})
2023-08-21 09:04:41 +00:00
})
return result
2023-07-03 05:20:24 +00:00
}
2023-08-28 13:31:52 +00:00
/**
* @param {string} channelID
* @param {string} messageID
* @param {DiscordTypes.RESTPatchAPIWebhookWithTokenMessageJSONBody & {files?: {name: string, file: Buffer | Readable}[]}} data
2023-08-28 13:31:52 +00:00
* @param {string} [threadID]
*/
async function editMessageWithWebhook(channelID, messageID, data, threadID) {
const result = await withWebhook(channelID, async webhook => {
return discord.snow.webhook.editWebhookMessage(webhook.id, webhook.token, messageID, {...data, thread_id: threadID})
})
return result
}
2023-08-30 01:14:23 +00:00
/**
* @param {string} channelID
* @param {string} messageID
* @param {string} [threadID]
*/
async function deleteMessageWithWebhook(channelID, messageID, threadID) {
const result = await withWebhook(channelID, async webhook => {
return discord.snow.webhook.deleteWebhookMessage(webhook.id, webhook.token, messageID, threadID)
})
return result
}
2023-06-30 03:15:34 +00:00
module.exports.ensureWebhook = ensureWebhook
module.exports.withWebhook = withWebhook
2023-07-03 05:20:24 +00:00
module.exports.sendMessageWithWebhook = sendMessageWithWebhook
2023-08-28 13:31:52 +00:00
module.exports.editMessageWithWebhook = editMessageWithWebhook
2023-08-30 01:14:23 +00:00
module.exports.deleteMessageWithWebhook = deleteMessageWithWebhook