2023-11-16 11:33:11 +01:00
import { AutocompleteInteraction , CommandInteraction , SlashCommandBuilder } from 'discord.js' ;
2023-11-22 09:40:37 +01:00
import { Counter , CustomCraftingRecipeItem , CustomItem , ItemBehavior , db } from '../lib/db' ;
import { customItemAutocomplete , formatItem , formatItems , getCustomItem , getItem , giveItem , isDefaultItem , itemAutocomplete } from '../lib/rpg/items' ;
2023-11-16 11:33:11 +01:00
import { Command } from '../types/index' ;
2023-11-18 14:03:52 +01:00
import { formatRecipe , getCustomRecipe } from '../lib/rpg/recipes' ;
2023-11-22 09:40:37 +01:00
import { behaviors , formatBehavior , getBehavior } from '../lib/rpg/behaviors' ;
2023-11-15 01:40:57 +01:00
//function extendOption(t: string) {
// return {name: t, value: t};
//}
2023-11-16 11:33:11 +01:00
export default {
2023-11-15 01:40:57 +01:00
data : new SlashCommandBuilder ( )
. setName ( 'item' )
. setDescription ( '[ADMIN] Create, edit and otherwise deal with custom items' )
. addSubcommandGroup ( grp = >
grp
. setName ( 'add' )
. setDescription ( '[ADMIN] Create an item' )
. addSubcommand ( cmd = >
cmd
. setName ( 'plain' )
. setDescription ( 'A normal, functionless item' )
. addStringOption ( opt = >
opt
. setName ( 'name' )
. setDescription ( 'The item name' )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'emoji' )
. setDescription ( 'An emoji or symbol that could represent this item' )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'description' )
. setDescription ( 'A short description' )
)
. addIntegerOption ( opt = >
opt
. setName ( 'maxstack' )
. setDescription ( 'Maximum amount of this item you\'re able to hold at once' )
)
. addBooleanOption ( opt = >
opt
. setName ( 'untradable' )
. setDescription ( 'Can you give this item to other people?' )
)
)
. addSubcommand ( cmd = >
cmd
. setName ( 'weapon' )
. setDescription ( 'A weapon that you can attack things with' )
. addStringOption ( opt = >
opt
. setName ( 'name' )
. setDescription ( 'The item name' )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'emoji' )
. setDescription ( 'An emoji or symbol that could represent this item' )
. setRequired ( true )
)
. addIntegerOption ( opt = >
opt
. setName ( 'damage' )
. setDescription ( 'How much base damage this weapon is intended to deal' )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'description' )
. setDescription ( 'A short description' )
)
. addBooleanOption ( opt = >
opt
. setName ( 'untradable' )
. setDescription ( 'Can you give this item to other people?' )
)
)
. addSubcommand ( cmd = >
cmd
. setName ( 'consumable' )
. setDescription ( 'Consumable item, usable once and never again' )
. addStringOption ( opt = >
opt
. setName ( 'name' )
. setDescription ( 'The item name' )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'emoji' )
. setDescription ( 'An emoji or symbol that could represent this item' )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'description' )
. setDescription ( 'A short description' )
)
. addIntegerOption ( opt = >
opt
. setName ( 'maxstack' )
. setDescription ( 'Maximum amount of this item you\'re able to hold at once' )
)
. addBooleanOption ( opt = >
opt
. setName ( 'untradable' )
. setDescription ( 'Can you give this item to other people?' )
)
)
)
. addSubcommand ( cmd = >
cmd
. setName ( 'give' )
. setDescription ( '[ADMIN] Give a user an item' )
. addUserOption ( opt = >
opt
. setName ( 'who' )
. setDescription ( 'The user' )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'item' )
. setDescription ( 'The item' )
. setAutocomplete ( true )
. setRequired ( true )
)
. addIntegerOption ( opt = >
opt
. setName ( 'quantity' )
. setDescription ( 'Amount of items to give' )
)
)
2023-11-18 14:03:52 +01:00
. addSubcommand ( cmd = >
cmd
. setName ( 'delete' )
. setDescription ( '[ADMIN] Delete a custom item' )
. addStringOption ( opt = >
opt
2023-11-18 15:12:27 +01:00
. setName ( 'customitem' )
2023-11-18 14:03:52 +01:00
. setDescription ( 'The item' )
. setAutocomplete ( true )
. setRequired ( true )
)
)
2023-11-22 09:40:37 +01:00
. addSubcommandGroup ( grp = >
grp
. setName ( 'behavior' )
. setDescription ( '[ADMIN] Item behavior management' )
. addSubcommand ( cmd = >
cmd
. setName ( 'add' )
. setDescription ( '[ADMIN] Give an item a behavior' )
. addStringOption ( opt = >
opt
. setName ( 'customitem' )
. setDescription ( 'The item' )
. setAutocomplete ( true )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'behavior' )
. setDescription ( 'The behavior to add' )
. setAutocomplete ( true )
. setRequired ( true )
)
. addNumberOption ( opt = >
opt
. setName ( 'value' )
. setDescription ( 'A value to assign the behavior, not always applicable' )
)
)
. addSubcommand ( cmd = >
cmd
. setName ( 'remove' )
. setDescription ( '[ADMIN] Rid an item of a behavior' )
. addStringOption ( opt = >
opt
. setName ( 'customitem' )
. setDescription ( 'The item' )
. setAutocomplete ( true )
. setRequired ( true )
)
. addStringOption ( opt = >
opt
. setName ( 'removebehavior' )
. setDescription ( 'The behavior to remove' )
. setAutocomplete ( true )
. setRequired ( true )
)
)
)
2023-11-15 01:40:57 +01:00
. setDefaultMemberPermissions ( '0' )
. setDMPermission ( false ) ,
2023-11-16 11:33:11 +01:00
execute : async ( interaction : CommandInteraction ) = > {
2023-11-15 01:40:57 +01:00
if ( ! interaction . isChatInputCommand ( ) ) return ;
await interaction . deferReply ( { ephemeral : true } ) ;
const subcommand = interaction . options . getSubcommand ( true ) ;
const group = interaction . options . getSubcommandGroup ( ) ;
if ( group === 'add' ) {
const item = await db < CustomItem > ( 'customItems' )
. insert ( {
'guild' : interaction . guildId ! ,
'name' : interaction . options . getString ( 'name' , true ) . trim ( ) ,
'description' : interaction . options . getString ( 'description' ) || undefined ,
'emoji' : interaction . options . getString ( 'emoji' , true ) . trim ( ) ,
'type' : subcommand as 'plain' | 'weapon' | 'consumable' , // kind of wild that ts makes you do this
'maxStack' : ( interaction . options . getInteger ( 'maxstack' ) || interaction . options . getInteger ( 'damage' ) ) || ( subcommand === 'weapon' ? 1 : 64 ) ,
'untradable' : interaction . options . getBoolean ( 'untradable' ) || false ,
} )
. returning ( '*' ) ;
await interaction . followUp ( ` ${ JSON . stringify ( item [ 0 ] ) } ` ) ;
2023-11-22 09:40:37 +01:00
} else if ( group === 'behavior' ) {
const itemID = parseInt ( interaction . options . getString ( 'customitem' , true ) ) ;
const item = await getCustomItem ( itemID ) ;
if ( ! item ) return await interaction . followUp ( 'No such item exists!' ) ;
if ( item . guild !== interaction . guildId ) return await interaction . followUp ( 'This item is from a different server! Nice try though' ) ;
if ( subcommand === 'add' ) {
const behaviorName = interaction . options . getString ( 'behavior' , true ) ;
const value = interaction . options . getNumber ( 'value' ) ;
const behavior = getBehavior ( behaviorName ) ;
if ( ! behavior ) return await interaction . followUp ( ` No such behavior ${ behaviorName } ! ` ) ;
const existingBehavior = await db < ItemBehavior > ( 'itemBehaviors' )
. where ( 'item' , item . id )
. where ( 'behavior' , behavior . name )
. first ( ) ;
if ( existingBehavior ) {
return await interaction . followUp ( ` ${ formatItem ( item ) } already has ** ${ formatBehavior ( behavior , existingBehavior . value ) } **! ` ) ;
}
await db < ItemBehavior > ( 'itemBehaviors' )
. insert ( {
item : item.id ,
behavior : behavior.name ,
value : value || undefined ,
} ) ;
return await interaction . followUp ( ` ${ formatItem ( item ) } now has ** ${ formatBehavior ( behavior , value || undefined ) } ** ` ) ;
} else if ( subcommand === 'remove' ) {
/////////////////// asngheasgyjdreajdneyonv
}
2023-11-15 01:40:57 +01:00
} else {
if ( subcommand === 'give' ) {
const user = interaction . options . getUser ( 'who' , true ) ;
const itemID = parseInt ( interaction . options . getString ( 'item' , true ) ) ;
const quantity = interaction . options . getInteger ( 'quantity' ) || 1 ;
const item = await getItem ( itemID ) ;
if ( ! item ) return interaction . followUp ( 'No such item exists!' ) ;
2023-11-22 09:40:37 +01:00
if ( ! isDefaultItem ( item ) ) {
if ( item . guild !== interaction . guildId ) return await interaction . followUp ( 'This item is from a different server! Nice try though' ) ;
}
2023-11-15 11:03:01 +01:00
const inv = await giveItem ( user . id , item , quantity ) ;
2023-11-15 01:40:57 +01:00
2023-11-15 11:03:01 +01:00
await interaction . followUp ( ` ${ user . toString ( ) } now has ${ formatItems ( item , inv . quantity ) } . ` ) ;
2023-11-18 14:03:52 +01:00
} else if ( subcommand === 'delete' ) {
2023-11-18 15:12:27 +01:00
const itemID = parseInt ( interaction . options . getString ( 'customitem' , true ) ) ;
2023-11-18 14:03:52 +01:00
const item = await getItem ( itemID ) ;
if ( ! item ) return interaction . followUp ( 'No such item exists!' ) ;
const usedIn = await db < CustomCraftingRecipeItem > ( 'customCraftingRecipeItems' )
. where ( 'item' , item . id ) ;
if ( usedIn . length > 0 ) {
const recipes = ( await Promise . all ( usedIn . map ( i = > getCustomRecipe ( i . id ) ) ) ) . filter ( r = > r !== undefined ) ;
return interaction . followUp ( ` ⚠️ This item is used in the following recipes: \ n ${ recipes . map ( r = > ` - ${ formatRecipe ( r ! ) } ` ) . join ( '\n' ) } ` ) ;
}
2023-11-21 21:31:00 +01:00
const linkedWith = await db < Counter > ( 'counters' )
. where ( 'linkedItem' , item . id ) ;
if ( linkedWith . length > 0 ) {
return interaction . followUp ( ` ⚠️ This item is used in the following counters: \ n ${ linkedWith . map ( c = > ` - ${ c . key } ${ c . value } in <# ${ c . channel } > ` ) . join ( '\n' ) } ` ) ;
}
2023-11-18 14:03:52 +01:00
await db < CustomItem > ( 'customItems' )
. where ( 'id' , item . id )
. delete ( ) ;
interaction . followUp ( ` ${ formatItem ( item ) } has been deleted. ` ) ;
2023-11-15 01:40:57 +01:00
}
}
} ,
autocomplete : async ( interaction : AutocompleteInteraction ) = > {
const focused = interaction . options . getFocused ( true ) ;
if ( focused . name === 'item' ) {
2023-11-15 11:03:01 +01:00
return itemAutocomplete ( interaction ) ;
2023-11-18 15:12:27 +01:00
} else if ( focused . name === 'customitem' ) {
return customItemAutocomplete ( interaction ) ;
2023-11-22 09:40:37 +01:00
} else if ( focused . name === 'behavior' ) {
let foundBehaviors = behaviors . filter ( b = > b . name . toLowerCase ( ) . includes ( focused . value . toLowerCase ( ) ) ) ;
const itemID = interaction . options . getString ( 'customitem' ) ;
if ( itemID ) {
const item = await getItem ( parseInt ( itemID ) ) ;
if ( item ) {
foundBehaviors = foundBehaviors . filter ( b = > b . itemType === item . type ) ;
}
}
await interaction . respond ( foundBehaviors . map ( b = > ( { name : ` ${ b . itemType } : ${ b . name } - ${ b . description } ` , value : b.name } ) ) ) ;
2023-11-15 01:40:57 +01:00
}
}
2023-11-16 11:33:11 +01:00
} satisfies Command ;