update_discord_message implemented
This commit is contained in:
parent
d08fcc0867
commit
54572dbebe
|
@ -6,7 +6,7 @@ import { configs } from './config.ts'
|
|||
export const bot = createProxyCache(
|
||||
createBot({
|
||||
token: configs.token,
|
||||
intents: Intents.Guilds
|
||||
intents: Intents.Guilds | Intents.GuildMessages
|
||||
}),
|
||||
{
|
||||
desiredProps: {
|
||||
|
|
|
@ -69,7 +69,7 @@ createCommand({
|
|||
{ name: 'Filesize', value: '0 bytes', inline: true},
|
||||
{ name: 'URL', value: url, inline: false }
|
||||
])
|
||||
.setColor('#33eb23')
|
||||
.setColor('#808080')
|
||||
|
||||
const response: InteractionCallbackData = { embeds }
|
||||
const message = await interaction.edit(response)
|
||||
|
|
|
@ -1,18 +1,35 @@
|
|||
|
||||
if (!process.env.WORKER_CONNECTION_STRING) throw new Error("WORKER_CONNECTION_STRING was missing from env");
|
||||
if (!process.env.POSTGREST_URL) throw new Error('Missing POSTGREST_URL env var');
|
||||
if (!process.env.DISCORD_TOKEN) throw new Error('Missing DISCORD_TOKEN env var');
|
||||
if (!process.env.DISCORD_CHANNEL_ID) throw new Error("DISCORD_CHANNEL_ID was missing from env");
|
||||
if (!process.env.DISCORD_GUILD_ID) throw new Error("DISCORD_GUILD_ID was missing from env");
|
||||
if (!process.env.AUTOMATION_USER_JWT) throw new Error('Missing AUTOMATION_USER_JWT env var');
|
||||
const token = process.env.DISCORD_TOKEN!
|
||||
const postgrestUrl = process.env.POSTGREST_URL!
|
||||
const discordChannelId = process.env.DISCORD_CHANNEL_ID!
|
||||
const discordGuildId = process.env.DISCORD_GUILD_ID!
|
||||
const automationUserJwt = process.env.AUTOMATION_USER_JWT!
|
||||
const connectionString = process.env.WORKER_CONNECTION_STRING!
|
||||
|
||||
console.log(`hello i am configs and configs.connectionString=${connectionString}`)
|
||||
|
||||
export const configs: Config = {
|
||||
token,
|
||||
postgrestUrl,
|
||||
automationUserJwt,
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
token: string;
|
||||
postgrestUrl: string;
|
||||
automationUserJwt: string;
|
||||
discordGuildId: string;
|
||||
discordChannelId: string;
|
||||
connectionString: string;
|
||||
}
|
||||
|
||||
|
||||
export const configs: Config = {
|
||||
token,
|
||||
postgrestUrl,
|
||||
automationUserJwt,
|
||||
discordGuildId,
|
||||
discordChannelId,
|
||||
connectionString,
|
||||
}
|
|
@ -1,14 +1,12 @@
|
|||
import 'dotenv/config'
|
||||
// import loadCommands from './loadCommands.js'
|
||||
// import deployCommands from './deployCommands.js'
|
||||
// import loadEvents from './loadEvents.js'
|
||||
// import updateDiscordMessage from './tasks/update_discord_message.js'
|
||||
import { type WorkerUtils } from 'graphile-worker'
|
||||
|
||||
import updateDiscordMessage from './tasks/update_discord_message.js'
|
||||
import { type WorkerUtils, type RunnerOptions, run } from 'graphile-worker'
|
||||
import { bot } from './bot.ts'
|
||||
import type { Interaction } from '@discordeno/bot'
|
||||
import { importDirectory } from './utils/loader.ts'
|
||||
import { join, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'url';
|
||||
import { configs } from './config.ts'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
|
@ -18,43 +16,36 @@ export interface ExecuteArguments {
|
|||
workerUtils: WorkerUtils;
|
||||
}
|
||||
|
||||
if (!process.env.AUTOMATION_USER_JWT) throw new Error(`AUTOMATION_USER_JWT was missing from env`);
|
||||
if (!process.env.DISCORD_TOKEN) throw new Error("DISCORD_TOKEN was missing from env");
|
||||
if (!process.env.DISCORD_CHANNEL_ID) throw new Error("DISCORD_CHANNEL_ID was missing from env");
|
||||
if (!process.env.DISCORD_GUILD_ID) throw new Error("DISCORD_GUILD_ID was missing from env");
|
||||
if (!process.env.WORKER_CONNECTION_STRING) throw new Error("WORKER_CONNECTION_STRING was missing from env");
|
||||
|
||||
const preset: GraphileConfig.Preset = {
|
||||
async function setupGraphileWorker() {
|
||||
const preset: GraphileConfig.Preset = {
|
||||
worker: {
|
||||
connectionString: process.env.WORKER_CONNECTION_STRING,
|
||||
connectionString: configs.connectionString,
|
||||
concurrentJobs: 3,
|
||||
fileExtensions: [".js", ".ts"]
|
||||
fileExtensions: [".js", ".ts"],
|
||||
taskDirectory: join(__dirname, 'tasks')
|
||||
},
|
||||
};
|
||||
};
|
||||
console.log('worker preset as follows')
|
||||
console.log(preset)
|
||||
const runnerOptions: RunnerOptions = {
|
||||
preset
|
||||
// concurrency: 3,
|
||||
// connectionString: configs.connectionString,
|
||||
// taskDirectory: join(__dirname, 'tasks'),
|
||||
// taskList: {
|
||||
// 'update_discord_message': updateDiscordMessage
|
||||
// }
|
||||
}
|
||||
|
||||
// async function setupGraphileWorker() {
|
||||
// const runnerOptions: RunnerOptions = {
|
||||
// preset,
|
||||
// taskList: {
|
||||
// 'updateDiscordMessage': updateDiscordMessage
|
||||
// }
|
||||
// }
|
||||
|
||||
// const runner = await run(runnerOptions)
|
||||
// if (!runner) throw new Error('failed to initialize graphile worker');
|
||||
// await runner.promise
|
||||
// }
|
||||
const runner = await run(runnerOptions)
|
||||
if (!runner) throw new Error('failed to initialize graphile worker');
|
||||
await runner.promise
|
||||
}
|
||||
|
||||
|
||||
// async function setupWorkerUtils() {
|
||||
// const workerUtils = await makeWorkerUtils({
|
||||
// preset
|
||||
// });
|
||||
// await workerUtils.migrate()
|
||||
// return workerUtils
|
||||
// }
|
||||
|
||||
async function main() {
|
||||
async function setupBot() {
|
||||
|
||||
bot.logger.info('Starting @futureporn/bot.')
|
||||
|
||||
|
@ -64,16 +55,15 @@ async function main() {
|
|||
bot.logger.info('Loading events...')
|
||||
await importDirectory(join(__dirname, './events'))
|
||||
|
||||
|
||||
// const commands = await loadCommands()
|
||||
// if (!commands) throw new Error('there were no commands available to be loaded.');
|
||||
// await deployCommands(commands.map((c) => c.data.toJSON()))
|
||||
// console.log(`${commands.length} commands deployed: ${commands.map((c) => c.data.name).join(', ')}`)
|
||||
// const workerUtils = await setupWorkerUtils()
|
||||
// setupGraphileWorker()
|
||||
await bot.start()
|
||||
}
|
||||
|
||||
|
||||
async function main() {
|
||||
await setupBot()
|
||||
await setupGraphileWorker()
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error("error during main() function")
|
||||
console.error(e)
|
||||
|
|
|
@ -3,9 +3,19 @@ import type { RecordingState } from '@futureporn/types'
|
|||
import { type Task, type Helpers } from 'graphile-worker'
|
||||
import { add } from 'date-fns'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import { EmbedsBuilder, type Component } from '@discordeno/bot'
|
||||
|
||||
|
||||
import {
|
||||
EmbedsBuilder,
|
||||
ButtonStyles,
|
||||
type ActionRow,
|
||||
MessageComponentTypes,
|
||||
type ButtonComponent,
|
||||
type InputTextComponent,
|
||||
type EditMessage,
|
||||
type Message,
|
||||
type Embed
|
||||
} from '@discordeno/bot'
|
||||
import { bot } from '../bot.ts'
|
||||
import { configs } from '../config.ts'
|
||||
|
||||
interface Payload {
|
||||
record_id: number;
|
||||
|
@ -19,11 +29,6 @@ function assertPayload(payload: any): asserts payload is Payload {
|
|||
}
|
||||
|
||||
|
||||
if (!process.env.AUTOMATION_USER_JWT) throw new Error(`AUTOMATION_USER_JWT was missing from env`);
|
||||
if (!process.env.DISCORD_TOKEN) throw new Error("DISCORD_TOKEN was missing from env");
|
||||
if (!process.env.DISCORD_CHANNEL_ID) throw new Error("DISCORD_CHANNEL_ID was missing from env");
|
||||
if (!process.env.DISCORD_GUILD_ID) throw new Error("DISCORD_GUILD_ID was missing from env");
|
||||
|
||||
|
||||
|
||||
async function editDiscordMessage({ helpers, recordingState, discordMessageId, url, fileSize, recordId }: { recordId: number, fileSize: number, url: string, helpers: Helpers, recordingState: RecordingState, discordMessageId: string }) {
|
||||
|
@ -35,45 +40,51 @@ async function editDiscordMessage({ helpers, recordingState, discordMessageId, u
|
|||
helpers.logger.info(`editDiscordMessage has begun with discordMessageId=${discordMessageId}, state=${recordingState}`)
|
||||
|
||||
|
||||
// create a discord.js client
|
||||
const client = new Client({
|
||||
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
|
||||
});
|
||||
// const guild = await bot.cache.guilds.get(BigInt(configs.discordGuildId))
|
||||
// const channel = guild?.channels.get(BigInt(configs.discordChannelId))
|
||||
|
||||
// Log in to Discord with your client's token
|
||||
client.login(process.env.DISCORD_TOKEN);
|
||||
// // const channel = await bot.cache.channels.get()
|
||||
// console.log('channel as follows')
|
||||
// console.log(channel)
|
||||
|
||||
const channelId = BigInt(configs.discordChannelId)
|
||||
const updatedMessage: EditMessage = {
|
||||
embeds: getStatusEmbed({ recordingState, fileSize, recordId, url }),
|
||||
}
|
||||
bot.helpers.editMessage(channelId, discordMessageId, updatedMessage)
|
||||
|
||||
// channel.
|
||||
|
||||
// const guild = await client.guilds.fetch(process.env.DISCORD_GUILD_ID!) as Guild
|
||||
// if (!guild) throw new Error('guild was undefined');
|
||||
|
||||
// helpers.logger.info('here is the guild as follows')
|
||||
// helpers.logger.info(guild.toString())
|
||||
// helpers.logger.info(`fetching discord channel id=${process.env.DISCORD_CHANNEL_ID} from discord guild`)
|
||||
// const channel = await client.channels.fetch(process.env.DISCORD_CHANNEL_ID!) as TextChannel
|
||||
// if (!channel) throw new Error(`discord channel was undefined`);
|
||||
|
||||
// const message = await channel.messages.fetch(discordMessageId)
|
||||
// helpers.logger.info(`discordMessageId=${discordMessageId}`)
|
||||
// helpers.logger.info(message as any)
|
||||
|
||||
// const statusEmbed = getStatusEmbed({ recordId, recordingState, fileSize, url })
|
||||
// const buttonRow = getButtonRow(recordingState)
|
||||
|
||||
|
||||
const guild = await client.guilds.fetch(process.env.DISCORD_GUILD_ID!) as Guild
|
||||
if (!guild) throw new Error('guild was undefined');
|
||||
|
||||
helpers.logger.info('here is the guild as follows')
|
||||
helpers.logger.info(guild.toString())
|
||||
helpers.logger.info(`fetching discord channel id=${process.env.DISCORD_CHANNEL_ID} from discord guild`)
|
||||
const channel = await client.channels.fetch(process.env.DISCORD_CHANNEL_ID!) as TextChannel
|
||||
if (!channel) throw new Error(`discord channel was undefined`);
|
||||
|
||||
const message = await channel.messages.fetch(discordMessageId)
|
||||
helpers.logger.info(`discordMessageId=${discordMessageId}`)
|
||||
helpers.logger.info(message as any)
|
||||
|
||||
const statusEmbed = getStatusEmbed({ recordId, recordingState, fileSize, url })
|
||||
const buttonRow = getButtonRow(recordingState)
|
||||
// // const embed = new EmbedBuilder().setTitle('Attachments');
|
||||
|
||||
|
||||
// const embed = new EmbedBuilder().setTitle('Attachments');
|
||||
// const updatedMessage = {
|
||||
// embeds: [
|
||||
// statusEmbed
|
||||
// ],
|
||||
// components: [
|
||||
// buttonRow
|
||||
// ]
|
||||
// };
|
||||
|
||||
|
||||
const updatedMessage = {
|
||||
embeds: [
|
||||
statusEmbed
|
||||
],
|
||||
components: [
|
||||
buttonRow
|
||||
]
|
||||
};
|
||||
|
||||
message.edit(updatedMessage)
|
||||
// message.edit(updatedMessage)
|
||||
|
||||
|
||||
}
|
||||
|
@ -121,14 +132,15 @@ export const updateDiscordMessage: Task = async function (payload, helpers: Help
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function getStatusEmbed({
|
||||
recordingState, recordId, fileSize, url
|
||||
}: { fileSize: number, recordingState: RecordingState, recordId: number, url: string }) {
|
||||
const embeds = new EmbedsBuilder()
|
||||
.setTitle(`Record ${recordId}`)
|
||||
.setFields([
|
||||
{ name: 'Status', value: 'Pending', inline: true },
|
||||
{ name: 'Filesize', value: `${fileSize} bytes (${prettyBytes(fileSize)})`, inline: true },
|
||||
{ name: 'Status', value: recordingState.charAt(0).toUpperCase()+recordingState.slice(1), inline: true },
|
||||
{ name: 'Filesize', value: prettyBytes(fileSize), inline: true },
|
||||
{ name: 'URL', value: url, inline: false },
|
||||
])
|
||||
if (recordingState === 'pending') {
|
||||
|
@ -157,72 +169,59 @@ function getStatusEmbed({
|
|||
|
||||
|
||||
|
||||
function getButtonRow(state: RecordingState) {
|
||||
function getButtonRow(state: RecordingState): ActionRow {
|
||||
const components: ButtonComponent[] = []
|
||||
|
||||
const button = new Component()
|
||||
.setType("BUTTON")
|
||||
|
||||
// // Button with raw types
|
||||
// const button2 = new Component()
|
||||
// .setType(2)
|
||||
// .setStyle(4)
|
||||
// .setLabel("DO NOT CLICK")
|
||||
// .setCustomId("12345")
|
||||
// .toJSON();
|
||||
|
||||
// const actionRow = new Component()
|
||||
// .setType("ACTION_ROW")
|
||||
// .setComponents(button, button2)
|
||||
// .toJSON();
|
||||
|
||||
// return actionRow
|
||||
|
||||
// Message to send
|
||||
// const messageOptions = { content: "hello", components: [actionRow] };
|
||||
|
||||
// await client.helpers.sendMessage(channelId, messageOptions); // You can also use the Message Structure
|
||||
|
||||
if (state === 'pending') {
|
||||
button
|
||||
.setCustomId('stop')
|
||||
.setLabel('Cancel')
|
||||
.setEmoji('❌')
|
||||
.setStyle('DANGER')
|
||||
} else if (state === 'recording') {
|
||||
button
|
||||
.setCustomId('stop')
|
||||
.setLabel('Stop Recording')
|
||||
.setEmoji('🛑')
|
||||
.setStyle('DANGER')
|
||||
if (state === 'pending' || state === 'recording') {
|
||||
const stopButton: ButtonComponent = {
|
||||
type: MessageComponentTypes.Button,
|
||||
customId: 'stop',
|
||||
label: 'Cancel',
|
||||
style: ButtonStyles.Danger
|
||||
}
|
||||
components.push(stopButton)
|
||||
} else if (state === 'aborted') {
|
||||
button
|
||||
.setCustomId('retry')
|
||||
.setLabel('Retry Recording')
|
||||
.setEmoji('🔄')
|
||||
.setStyle('SUCCESS')
|
||||
const retryButton: ButtonComponent = {
|
||||
type: MessageComponentTypes.Button,
|
||||
customId: 'retry',
|
||||
label: 'Retry Recording',
|
||||
emoji: {
|
||||
name: 'retry'
|
||||
},
|
||||
style: ButtonStyles.Secondary
|
||||
}
|
||||
components.push(retryButton)
|
||||
} else if (state === 'ended') {
|
||||
button
|
||||
.setCustomId('download')
|
||||
.setLabel('Download Recording')
|
||||
.setEmoji('📥')
|
||||
.setStyle('PRIMARY')
|
||||
const downloadButton: ButtonComponent = {
|
||||
type: MessageComponentTypes.Button,
|
||||
customId: 'download',
|
||||
label: 'Download Recording',
|
||||
emoji: {
|
||||
id: BigInt('1253191939461873756')
|
||||
},
|
||||
style: ButtonStyles.Success
|
||||
}
|
||||
components.push(downloadButton)
|
||||
} else {
|
||||
button
|
||||
.setCustomId('unknown')
|
||||
.setLabel('Unknown State')
|
||||
.setEmoji('🤔')
|
||||
.setStyle('SECONDARY')
|
||||
const unknownButton: ButtonComponent = {
|
||||
type: MessageComponentTypes.Button,
|
||||
customId: 'unknown',
|
||||
label: 'Unknown State',
|
||||
emoji: {
|
||||
name: 'thinking'
|
||||
},
|
||||
style: ButtonStyles.Primary
|
||||
}
|
||||
components.push(unknownButton)
|
||||
}
|
||||
|
||||
const actionRow = new Component
|
||||
return new ActionRowBuilder<MessageActionRowComponentBuilder>()
|
||||
.addComponents([
|
||||
new ButtonBuilder()
|
||||
.setCustomId(id)
|
||||
.setLabel(label)
|
||||
.setEmoji(emoji)
|
||||
.setStyle(style),
|
||||
]);
|
||||
|
||||
const actionRow: ActionRow = {
|
||||
type: MessageComponentTypes.ActionRow,
|
||||
components: components as [ButtonComponent]
|
||||
}
|
||||
|
||||
return actionRow
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ export default class Record {
|
|||
|
||||
parallelUploads3.on("httpUploadProgress", (progress) => {
|
||||
if (progress?.loaded) {
|
||||
if (this.onProgress) this.onProgress(this.counter);
|
||||
console.log(`uploaded ${progress.loaded} bytes (${prettyBytes(progress.loaded)})`);
|
||||
} else {
|
||||
console.log(`httpUploadProgress ${JSON.stringify(progress, null, 2)}`)
|
||||
|
@ -158,12 +159,9 @@ export default class Record {
|
|||
|
||||
|
||||
// streams setup
|
||||
|
||||
this.uploadStream.on('data', (data) => {
|
||||
this.counter += data.length
|
||||
if (this.counter % (1 * 1024 * 1024) <= 1024) {
|
||||
console.log(`Received ${this.counter} bytes (${prettyBytes(this.counter)})`);
|
||||
if (this.onProgress) this.onProgress(this.counter)
|
||||
}
|
||||
})
|
||||
this.uploadStream.on('close', () => {
|
||||
console.log('[!!!] upload stream has closed')
|
||||
|
|
|
@ -67,7 +67,16 @@ function checkIfAborted(record: RawRecordingRecord): boolean {
|
|||
return (record.is_aborted)
|
||||
}
|
||||
|
||||
async function updateDatabaseRecord({recordId, recordingState, fileSize}: { recordId: number, recordingState: RecordingState, fileSize: number }): Promise<RawRecordingRecord> {
|
||||
async function updateDatabaseRecord({
|
||||
recordId,
|
||||
recordingState,
|
||||
fileSize
|
||||
}: {
|
||||
recordId: number,
|
||||
recordingState: RecordingState,
|
||||
fileSize: number
|
||||
}): Promise<RawRecordingRecord> {
|
||||
console.log(`updating database record with recordId=${recordId}, recordingState=${recordingState}, fileSize=${fileSize}`)
|
||||
const payload: any = {
|
||||
file_size: fileSize
|
||||
}
|
||||
|
@ -83,7 +92,8 @@ async function updateDatabaseRecord({recordId, recordingState, fileSize}: { reco
|
|||
body: JSON.stringify(payload)
|
||||
})
|
||||
if (!res.ok) {
|
||||
throw new Error(`failed to updateDatabaseRecord. status=${res.status}, statusText=${res.statusText}`);
|
||||
const body = await res.text()
|
||||
throw new Error(`failed to updateDatabaseRecord. status=${res.status}, statusText=${res.statusText}, body=${body}`);
|
||||
}
|
||||
const body = await res.json() as RawRecordingRecord[];
|
||||
if (!body[0]) throw new Error(`failed to get a record that matched recordId=${recordId}`)
|
||||
|
|
|
@ -5,7 +5,7 @@ CREATE FUNCTION public.tg__update_discord_message() RETURNS trigger
|
|||
AS $$
|
||||
begin
|
||||
PERFORM graphile_worker.add_job('update_discord_message', json_build_object(
|
||||
'record_id', NEW.record_id
|
||||
'record_id', NEW.id
|
||||
), max_attempts := 3);
|
||||
return NEW;
|
||||
end;
|
||||
|
|
Loading…
Reference in New Issue