initial commit
This commit is contained in:
221
commands/images/image.ts
Normal file
221
commands/images/image.ts
Normal file
@@ -0,0 +1,221 @@
|
||||
import discord, {
|
||||
CommandInteraction,
|
||||
CommandInteractionOptionResolver,
|
||||
SlashCommandBuilder,
|
||||
SlashCommandStringOption,
|
||||
SlashCommandAttachmentOption,
|
||||
SlashCommandSubcommandBuilder,
|
||||
EmbedBuilder,
|
||||
InteractionResponse,
|
||||
SlashCommandSubcommandsOnlyBuilder,
|
||||
Attachment
|
||||
} from 'discord.js';
|
||||
import { HydratedDocument } from 'mongoose';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import axios from 'axios';
|
||||
import { Client } from 'minio';
|
||||
|
||||
import { Command } from '../../classes/command';
|
||||
import { logger } from '../../logger';
|
||||
import { config } from '../../config';
|
||||
import { reactPreprocess } from '../../functions/react-preprocess';
|
||||
import { Image, imageModel } from '../../models/Image';
|
||||
import { Alias, aliasModel } from '../../models/Alias';
|
||||
import { Guild, guildModel } from '../../models/Guild';
|
||||
import { Token, tokenModel } from '../../models/Token';
|
||||
|
||||
type CIOR = CommandInteractionOptionResolver;
|
||||
|
||||
const client = new Client(config.minio.client);
|
||||
|
||||
async function download(url: string, file: string): Promise<void>{
|
||||
const saveFile = await axios({
|
||||
url: url, method: 'GET', responseType: 'arraybuffer'
|
||||
});
|
||||
if(!await client.bucketExists(config.minio.bucket))
|
||||
await client.makeBucket(config.minio.bucket);
|
||||
|
||||
await client.putObject(config.minio.bucket, file, saveFile.data);
|
||||
}
|
||||
|
||||
async function upload(interaction: CommandInteraction): Promise<void>{
|
||||
if(!interaction.guildId)
|
||||
throw Error('guildId not exist');
|
||||
const file: discord.Attachment | null =
|
||||
(interaction.options as CIOR).getAttachment('file');
|
||||
if(!file)
|
||||
throw Error('file not exist');
|
||||
const fileExt: string = path.extname(file.name);
|
||||
|
||||
const image: HydratedDocument<Image> | null =
|
||||
await (new imageModel({extension: fileExt})).save();
|
||||
if(!image)
|
||||
throw Error('image not exist');
|
||||
await download(file.url, `${String(image._id)}${fileExt}`);
|
||||
|
||||
const publicUrl: string = `${config.httpServer.external.url}/${String(image._id)}${fileExt}`;
|
||||
await interaction.reply({
|
||||
content: logger.log(`Image saved with id: ${image._id}.`),
|
||||
});
|
||||
if(interaction.channel)
|
||||
await interaction.channel.send({content: publicUrl});
|
||||
}
|
||||
|
||||
async function link(interaction: CommandInteraction): Promise<void>{
|
||||
if(!interaction.guildId)
|
||||
throw Error('guildId not exist');
|
||||
let aliasText: string | null =
|
||||
(interaction.options as CIOR).getString('alias');
|
||||
if(!aliasText)
|
||||
throw Error('aliasText not exist');
|
||||
const imageId: string | null =
|
||||
(interaction.options as CIOR).getString('image');
|
||||
if(!imageId)
|
||||
throw Error('imageId not exist');
|
||||
|
||||
aliasText = reactPreprocess(aliasText);
|
||||
if(!interaction.guild || !interaction.guild.id || !interaction.guild.name)
|
||||
throw Error('guild not exist');
|
||||
const guild: HydratedDocument<Guild> | null =
|
||||
await guildModel.findOneAndUpdate(
|
||||
{id: interaction.guild.id},
|
||||
{$set: {name: interaction.guild.name}},
|
||||
{new: true, upsert: true}
|
||||
);
|
||||
if(!guild)
|
||||
throw Error('guild not exist');
|
||||
const image: HydratedDocument<Image> | null =
|
||||
await imageModel.findById(imageId);
|
||||
if(!image)
|
||||
throw Error('image not exist');
|
||||
const alias: HydratedDocument<Alias> | null =
|
||||
await aliasModel.findOneAndUpdate(
|
||||
{guild: guild, text: aliasText, images: {$nin: image}},
|
||||
{$push: {images: image}},
|
||||
{new: true, upsert: true}
|
||||
);
|
||||
if(!alias)
|
||||
throw Error('alias update failed');
|
||||
|
||||
await interaction.reply({
|
||||
content: logger.log(`Alias ${aliasText} has linked to image id: ${imageId}.`)
|
||||
});
|
||||
}
|
||||
|
||||
async function unlink(interaction: CommandInteraction): Promise<void>{
|
||||
if(!interaction.guildId)
|
||||
throw Error('guildId not exist');
|
||||
let aliasText: string | null =
|
||||
(interaction.options as CIOR).getString('alias');
|
||||
if(!aliasText)
|
||||
throw Error('aliasText not exist');
|
||||
aliasText = reactPreprocess(aliasText);
|
||||
if(!interaction.guild || !interaction.guild.id)
|
||||
throw Error('guild not exist');
|
||||
const guild: HydratedDocument<Guild> | null =
|
||||
await guildModel.findOne({id: interaction.guild.id});
|
||||
if(!guild)
|
||||
throw Error('guild not exist');
|
||||
const res = await aliasModel.deleteOne(
|
||||
{guild: guild, text: aliasText}
|
||||
);
|
||||
if(!res)
|
||||
logger.warning('alias not exist');
|
||||
|
||||
await interaction.reply({
|
||||
content: logger.log(`All the image have been unlinked to alias ${aliasText}.`)
|
||||
});
|
||||
}
|
||||
|
||||
async function list(interaction: CommandInteraction): Promise<void>{
|
||||
const token: string = String(Math.floor(Math.random() * 100000000));
|
||||
if(!interaction.guild || !interaction.guild.id)
|
||||
throw Error('guild not exist');
|
||||
await tokenModel.create({
|
||||
token: token,
|
||||
guildId: interaction.guild.id,
|
||||
exp: Date.now() + config.tokenTimeLimit
|
||||
});
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(0x1f1e33)
|
||||
.setTitle('Autoreact Image List')
|
||||
.setDescription('experimental function')
|
||||
.addFields({
|
||||
name: 'One Time Link:',
|
||||
value: `[open in browser](https://amane.konchin.com/auth?token=${token})`
|
||||
});
|
||||
await interaction.reply({embeds: [embed], ephemeral: true});
|
||||
}
|
||||
|
||||
class ImageCmd extends Command{
|
||||
get name(){return "image";}
|
||||
get description(){return "Modify the reacting image database.";}
|
||||
async execute(interaction: CommandInteraction): Promise<void>{
|
||||
try{
|
||||
const subcommand: string | null =
|
||||
(interaction.options as CIOR).getSubcommand();
|
||||
switch(subcommand){
|
||||
case 'upload':
|
||||
await upload(interaction); break;
|
||||
case 'link':
|
||||
await link(interaction); break;
|
||||
case 'unlink':
|
||||
await unlink(interaction); break;
|
||||
case 'list':
|
||||
await list(interaction); break;
|
||||
default:
|
||||
throw Error('subcommand not exist');
|
||||
}
|
||||
}catch(err: unknown){
|
||||
let message;
|
||||
if(err instanceof Error) message = err.message;
|
||||
else message = String(message);
|
||||
logger.error(`While executing "/image", ${message}`);
|
||||
await interaction.reply({content: `While executing "/image", ${message}`});
|
||||
}
|
||||
}
|
||||
override build(): SlashCommandSubcommandsOnlyBuilder{
|
||||
return new SlashCommandBuilder()
|
||||
.setName(this.name)
|
||||
.setDescription(this.description)
|
||||
.addSubcommand((subcommand: SlashCommandSubcommandBuilder) => subcommand
|
||||
.setName('upload')
|
||||
.setDescription('Upload an image.')
|
||||
.addAttachmentOption((option: SlashCommandAttachmentOption) => option
|
||||
.setName('file')
|
||||
.setDescription('The image file that you want to upload.')
|
||||
.setRequired(true)
|
||||
)
|
||||
)
|
||||
.addSubcommand((subcommand: SlashCommandSubcommandBuilder) => subcommand
|
||||
.setName('link')
|
||||
.setDescription('Link an alias to an image')
|
||||
.addStringOption((option: SlashCommandStringOption) => option
|
||||
.setName('alias')
|
||||
.setDescription('The alias to be linked.')
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option: SlashCommandStringOption) => option
|
||||
.setName('image')
|
||||
.setDescription('The image to be linked, as id.')
|
||||
.setRequired(true)
|
||||
)
|
||||
)
|
||||
.addSubcommand((subcommand: SlashCommandSubcommandBuilder) => subcommand
|
||||
.setName('unlink')
|
||||
.setDescription('Unlink an alias to an image')
|
||||
.addStringOption((option: SlashCommandStringOption) => option
|
||||
.setName('alias')
|
||||
.setDescription('The alias to be unlinked.')
|
||||
.setRequired(true)
|
||||
)
|
||||
)
|
||||
.addSubcommand((subcommand: SlashCommandSubcommandBuilder) => subcommand
|
||||
.setName('list')
|
||||
.setDescription('Show the image list')
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
export const command = new ImageCmd();
|
||||
Reference in New Issue
Block a user