99 lines
No EOL
3.6 KiB
TypeScript
99 lines
No EOL
3.6 KiB
TypeScript
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, CacheType, ChatInputCommandInteraction, Events, Interaction, InteractionReplyOptions, MessageFlags, SlashCommandBuilder, User } from "discord.js";
|
|
import { db } from "../db/db";
|
|
import { b64decode, b64encode } from "../lib/b64";
|
|
import { createEmbed } from "../lib/embed";
|
|
import { formatSize } from "../lib/files";
|
|
import { StereoFile } from "../types/files";
|
|
|
|
export const data = new SlashCommandBuilder()
|
|
.setName("files")
|
|
.setDescription("list all of your files")
|
|
.addIntegerOption(option =>
|
|
option.setName("page")
|
|
.setDescription("page number to view")
|
|
.setRequired(false)
|
|
.setMinValue(1)
|
|
);
|
|
|
|
export async function renderList(user: User, userId: string, page: number): Promise<InteractionReplyOptions> {
|
|
const amount = 3;
|
|
|
|
const { count } = await db.get<{ count: number }>`
|
|
SELECT COUNT(*) as count FROM files WHERE owner = ${userId}
|
|
`;
|
|
|
|
const totalPages = Math.max(1, Math.ceil(count / amount));
|
|
const pages = Math.max(1, Math.min(page, totalPages));
|
|
|
|
const files = await db.all<StereoFile[]>`
|
|
SELECT * FROM files WHERE owner = ${userId}
|
|
ORDER BY created_at DESC
|
|
LIMIT ${amount} OFFSET ${(pages - 1) * amount}
|
|
`;
|
|
|
|
if (files.length === 0) {
|
|
return { content: "you havn't uploaded any files yet, visit the website to get started!", flags: MessageFlags.Ephemeral };
|
|
}
|
|
|
|
const embed = createEmbed(user)
|
|
.setTitle("your files")
|
|
.addFields(...files.map(file => ({
|
|
name: `\`${file.name}\``,
|
|
value: `${formatSize(file.size)}\n${new Date(file.created_at).toLocaleString()}\n[open in browser](${process.env.API}/${file.id})`,
|
|
inline: true
|
|
})))
|
|
.setFooter({ text: `page ${pages} of ${totalPages}` });
|
|
|
|
if (totalPages <= 1) {
|
|
return { embeds: [embed] }
|
|
}
|
|
|
|
const row = new ActionRowBuilder<ButtonBuilder>()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId(b64encode({ direction: -1, user: userId, pages: pages }))
|
|
.setLabel('<')
|
|
.setStyle(ButtonStyle.Danger)
|
|
.setDisabled(pages === 1),
|
|
new ButtonBuilder()
|
|
.setCustomId(b64encode({ direction: 1, user: userId, pages: pages }))
|
|
.setLabel('>')
|
|
.setStyle(ButtonStyle.Danger)
|
|
.setDisabled(pages === totalPages)
|
|
);
|
|
|
|
return { embeds: [embed], components: [row] };
|
|
}
|
|
|
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|
const page = interaction.options.getInteger("page") || 1;
|
|
const userId = interaction.user.id;
|
|
const reply = await renderList(interaction.user, userId, page);
|
|
await interaction.reply(reply);
|
|
};
|
|
|
|
export const on: {
|
|
[event in Events]?: (interaction: Interaction<CacheType>) => Promise<void>;
|
|
} = {
|
|
[Events.InteractionCreate]: async (interaction: Interaction<CacheType>) => {
|
|
if (!interaction.isButton()) return;
|
|
|
|
const data = b64decode<{
|
|
direction: -1 | 1;
|
|
user: string;
|
|
pages: number;
|
|
}>(interaction.customId);
|
|
|
|
if (interaction.user.id !== data.user) {
|
|
await interaction.reply({ content: "hey, stop that!!!", flags: MessageFlags.Ephemeral });
|
|
return;
|
|
}
|
|
|
|
const page = data.pages + data.direction;
|
|
const dirty = await renderList(interaction.user, interaction.user.id, page);
|
|
const { flags, ...r } = dirty;
|
|
await interaction.update({ ...r });
|
|
}
|
|
}
|
|
|
|
export default [data, execute, on] as const; |