Discord bot to open dong files

finish it

Vielle.dev 5536eb90 6d5e9ce7

Changed files
+86 -26
src
commands
lib
+6
bun.lock
··· 4 4 "": { 5 5 "name": "discord", 6 6 "dependencies": { 7 + "@types/mime": "^4.0.0", 7 8 "discord.js": "^14.18.0", 9 + "mime": "^4.0.6", 8 10 }, 9 11 "devDependencies": { 10 12 "@types/bun": "latest", ··· 35 37 36 38 "@types/bun": ["@types/bun@1.2.4", "", { "dependencies": { "bun-types": "1.2.4" } }, "sha512-QtuV5OMR8/rdKJs213iwXDpfVvnskPXY/S0ZiFbsTjQZycuqPbMW8Gf/XhLfwE5njW8sxI2WjISURXPlHypMFA=="], 37 39 40 + "@types/mime": ["@types/mime@4.0.0", "", { "dependencies": { "mime": "*" } }, "sha512-5eEkJZ/BLvTE3vXGKkWlyTSUVZuzj23Wj8PoyOq2lt5I3CYbiLBOPb3XmCW6QcuOibIUE6emHXHt9E/F/rCa6w=="], 41 + 38 42 "@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], 39 43 40 44 "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], ··· 54 58 "lodash.snakecase": ["lodash.snakecase@4.1.1", "", {}, "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="], 55 59 56 60 "magic-bytes.js": ["magic-bytes.js@1.10.0", "", {}, "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ=="], 61 + 62 + "mime": ["mime@4.0.6", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-4rGt7rvQHBbaSOF9POGkk1ocRP16Md1x36Xma8sz8h8/vfCUI2OtEIeCqe4Ofes853x4xDoPiFLIT47J5fI/7A=="], 57 63 58 64 "ts-mixer": ["ts-mixer@6.0.4", "", {}, "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="], 59 65
+3 -1
package.json
··· 14 14 "typescript": "^5" 15 15 }, 16 16 "dependencies": { 17 - "discord.js": "^14.18.0" 17 + "@types/mime": "^4.0.0", 18 + "discord.js": "^14.18.0", 19 + "mime": "^4.0.6" 18 20 } 19 21 }
+16 -19
src/commands/dong/create.ts
··· 1 1 import { 2 2 Attachment, 3 + AttachmentBuilder, 3 4 ChatInputCommandInteraction, 4 5 SlashCommandBuilder, 5 6 } from "discord.js"; 6 7 import type { customClient } from "../.."; 7 - 8 - const download = async (file: Attachment): Promise<File> => 9 - new File( 10 - [ 11 - await fetch(file.url).then((res) => { 12 - return res.blob(); 13 - }), 14 - ], 15 - file.name, 16 - { 17 - type: file.contentType ?? "application/octet-stream", 18 - } 19 - ); 8 + import { createDong } from "../../lib/dong-io"; 9 + import { download } from "../../lib/download"; 20 10 21 11 export const data = new SlashCommandBuilder() 22 12 .setName("create") ··· 62 52 audio: await download(audio), 63 53 }; 64 54 console.log(downloaded); 65 - await interaction.editReply(`Not implemented! Debug: 66 - \`\`\` 67 - filename: ${filename} 68 55 69 - image: ${image.contentType} | ${image.url} 56 + const dong = new File( 57 + [await createDong(downloaded.image, downloaded.audio)], 58 + filename, 59 + { type: "application/prs.vielle.dong" } 60 + ); 61 + console.log(dong); 70 62 71 - audio: ${audio.contentType} | ${audio.url} 72 - \`\`\``); 63 + await interaction.editReply({ 64 + files: [ 65 + new AttachmentBuilder(Buffer.from(await dong.arrayBuffer()), { 66 + name: dong.name, 67 + }), 68 + ], 69 + }); 73 70 };
+47 -6
src/commands/dong/open.ts
··· 1 - import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; 1 + import { 2 + AttachmentBuilder, 3 + ChatInputCommandInteraction, 4 + SlashCommandBuilder, 5 + } from "discord.js"; 2 6 import type { customClient } from "../.."; 7 + import { download } from "../../lib/download"; 8 + import { readDong } from "../../lib/dong-io"; 9 + import { Mime } from "mime"; 10 + import standardTypes from "mime/types/standard.js"; 11 + import otherTypes from "mime/types/other.js"; 12 + 13 + const mime = new Mime(standardTypes, otherTypes); 14 + mime.define({ "audio/mpeg": ["mp3"] }); 3 15 4 16 export const data = new SlashCommandBuilder() 5 17 .setName("open") 6 18 .setDescription("Open a dong file!") 7 19 .addAttachmentOption((opt) => 8 - opt 9 - .setName("dong") 10 - .setDescription("The dong file") 11 - .setRequired(true) 20 + opt.setName("dong").setDescription("The dong file").setRequired(true) 12 21 ); 13 22 export const execute = async ( 14 23 interaction: ChatInputCommandInteraction & { client: customClient } 15 24 ) => { 16 - await interaction.reply("Not Implemented!"); 25 + const dong = interaction.options.getAttachment("dong", true); 26 + await interaction.deferReply(); 27 + 28 + const downloadedDong = await download(dong); 29 + console.log(downloadedDong); 30 + 31 + const output = await readDong(downloadedDong); 32 + if (typeof output === "string") { 33 + await interaction.editReply(output); 34 + return; 35 + } 36 + const { image, audio } = output; 37 + 38 + console.log(image, audio); 39 + 40 + await interaction.editReply({ 41 + files: [ 42 + (() => { 43 + const img = new AttachmentBuilder(Buffer.from(image.data.buffer), { 44 + name: `${dong.name.match(/^.*(?=\.dong$)/gm)}.${mime.getExtension( 45 + image.mime 46 + )}`, 47 + }); 48 + img.setSpoiler(true); 49 + return img; 50 + })(), 51 + new AttachmentBuilder(Buffer.from(audio.data.buffer), { 52 + name: `${dong.name.match(/^.*(?=\.dong$)/gm)}.${mime.getExtension( 53 + audio.mime 54 + )}`, 55 + }), 56 + ], 57 + }); 17 58 };
+14
src/lib/download.ts
··· 1 + import type { Attachment } from "discord.js"; 2 + 3 + export const download = async (file: Attachment): Promise<File> => 4 + new File( 5 + [ 6 + await fetch(file.url).then((res) => { 7 + return res.blob(); 8 + }), 9 + ], 10 + file.name, 11 + { 12 + type: file.contentType ?? "application/octet-stream", 13 + } 14 + );