1
0
Fork 0

add webhook creation utility

This commit is contained in:
Cadence Ember 2023-06-30 15:15:34 +12:00
parent cc1210729f
commit 5bd1bc9a5b
4 changed files with 79 additions and 0 deletions

View file

@ -0,0 +1,50 @@
// @ts-check
const assert = require("assert").strict
const passthrough = require("../../passthrough")
const {discord, db} = passthrough
/**
* 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) {
/** @type {{id: string, token: string} | null} */
const row = db.prepare("SELECT webhook_id as id, webhook_token as token FROM webhook WHERE channel_id = ?").get(channelID)
if (row) {
return {created: false, ...row}
}
}
// 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 => {
console.error(e)
// TODO: check if the error was webhook-related and if webhook.created === false, then: const webhook = ensureWebhook(channelID, true); return callback(webhook)
throw new Error(e)
})
}
module.exports.ensureWebhook = ensureWebhook
module.exports.withWebhook = withWebhook

View file

@ -0,0 +1,23 @@
// @ts-check
const assert = require("assert").strict
const DiscordTypes = require("discord-api-types/v10")
const passthrough = require("../../passthrough")
const {sync, discord, db} = passthrough
/** @type {import("./register-webhook")} */
const registerWebhook = sync.require("./register-webhook")
/**
* @param {string} channelID
* @param {DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {name: string, file: Buffer}[]} data
*/
// param {DiscordTypes.RESTPostAPIWebhookWithTokenQuery & {wait: true, disableEveryone?: boolean}} options
async function sendMessage(channelID, data) {
const result = await registerWebhook.withWebhook(channelID, async webhook => {
return discord.snow.webhook.executeWebhook(webhook.id, webhook.token, data, {wait: true, disableEveryone: true})
})
return result
}
module.exports.sendMessage = sendMessage

View file

@ -17,3 +17,4 @@ require("../matrix/read-registration.test")
require("../d2m/converters/message-to-event.test") require("../d2m/converters/message-to-event.test")
require("../d2m/actions/create-room.test") require("../d2m/actions/create-room.test")
require("../d2m/converters/user-to-mxid.test") require("../d2m/converters/user-to-mxid.test")
require("../d2m/actions/register-user.test")

5
types.d.ts vendored
View file

@ -9,6 +9,11 @@ export type AppServiceRegistrationConfig = {
rate_limited: boolean rate_limited: boolean
} }
export type WebhookCreds = {
id: string
token: string
}
namespace Event { namespace Event {
export type BaseStateEvent = { export type BaseStateEvent = {
type: string type: string