Compare commits

...

10 Commits

11 changed files with 218 additions and 26 deletions

View File

@ -48,7 +48,6 @@ export const data = new SlashCommandBuilder()
.setRequired(true)
)
);
/** @param {ChatInputCommandInteraction} interaction */
export async function execute(interaction) {
const { options } = interaction;

View File

@ -0,0 +1,139 @@
import {
SlashCommandBuilder,
PermissionFlagsBits,
ModalSubmitInteraction,
AutocompleteInteraction,
ChatInputCommandInteraction
} from 'discord.js';
/** @param {ChatInputCommandInteraction} interaction */
async function createResponse(interaction) {}
/** @param {ChatInputCommandInteraction} interaction */
async function addResponse(interaction) {}
/** @param {ChatInputCommandInteraction} interaction */
async function removeResponse(interaction) {}
/** @param {ChatInputCommandInteraction} interaction */
async function listResponse(interaction) {}
/** @param {ChatInputCommandInteraction} interaction */
async function infoResponse(interaction) {}
/** @param {AutocompleteInteraction} interaction */
async function addAutocomplete(interaction) {}
/** @param {AutocompleteInteraction} interaction */
async function removeAutocomplete(interaction) {}
/** @param {AutocompleteInteraction} interaction */
async function infoAutocomplete(interaction) {}
export const data = new SlashCommandBuilder()
.setName('response')
.setDMPermission(false)
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages)
.setDescription('Event based responses to specific messages with keywords.')
.addSubcommand((subcommand) =>
subcommand
.setName('create')
.setDescription('Creates a new event based response.')
.addStringOption((option) =>
option
.setName('keyword')
.setDescription('The keyword to trigger the response.')
.setRequired(true)
)
)
.addSubcommand((subcommand) =>
subcommand
.setName('add')
.setDescription('Registers a response to a keyword.')
.addStringOption((option) =>
option
.setName('keyword')
.setDescription('The keyword to trigger the response.')
.setAutocomplete(true)
.setRequired(true)
)
)
.addSubcommand((subcommand) =>
subcommand
.setName('remove')
.setDescription('Unregisters a response to a keyword.')
.addStringOption((option) =>
option
.setName('type')
.setDescription('The type of data to be removed.')
.setRequired(true)
.addChoices(
{ name: 'Keyword', value: 'keyword' },
{ name: 'Response', value: 'response' }
)
)
.addStringOption((option) =>
option
.setName('name')
.setDescription('The name of the data to be removed.')
.setAutocomplete(true)
.setRequired(true)
)
)
.addSubcommand((subcommand) =>
subcommand.setName('list').setDescription('Lists all registered keywords.')
)
.addSubcommand((subcommand) =>
subcommand
.setName('info')
.setDescription('Shows information about a registered keyword.')
.addStringOption((option) =>
option
.setName('keyword')
.setDescription('The keyword to show the details of.')
.setAutocomplete(true)
.setRequired(true)
)
);
/** @param {ModalSubmitInteraction} interaction */
export async function modalSubmit(interaction) {
// Only executable in 'add' subcommand
}
/** @param {AutocompleteInteraction} interaction */
export async function autocomplete(interaction) {
const { options } = interaction;
switch (options.getSubcommand()) {
case 'add':
addAutocomplete(interaction);
break;
case 'remove':
removeAutocomplete(interaction);
break;
case 'info':
infoAutocomplete(interaction);
break;
}
}
/** @param {ChatInputCommandInteraction} interaction */
export async function execute(interaction) {
const { options } = interaction;
switch (options.getSubcommand()) {
case 'create':
createResponse(interaction);
break;
case 'add':
addResponse(interaction);
break;
case 'remove':
removeResponse(interaction);
break;
case 'list':
listResponse(interaction);
break;
case 'info':
infoResponse(interaction);
break;
}
}

View File

@ -37,6 +37,7 @@ const createSelfRoles = async (interaction) => {
const registerSelfRoles = async (interaction) => {
const { options, channel } = interaction;
const id = options.getString('id');
/** @type {SelfRoleResponse} */
const response = {
success: false,
msgID: null

View File

@ -1,6 +1,8 @@
import defineRoleEmojiPair from './models/roleEmojiPairs.js';
import defineVoiceChannel from './models/voiceChannels.js';
import defineResponse from './models/responses.js';
import defineMessage from './models/messages.js';
import defineKeyword from './models/keywords.js';
import defineGuild from './models/guilds.js';
import defineRole from './models/roles.js';
import { Sequelize } from 'sequelize';
@ -16,6 +18,11 @@ const sequelize = new Sequelize({
logging: false
});
const Response = defineResponse(sequelize);
const Keyword = defineKeyword(sequelize);
Keyword.hasMany(Response, { foreignKey: 'keyword', onDelete: 'CASCADE' });
const RoleEmojiPair = defineRoleEmojiPair(sequelize);
const VoiceChannel = defineVoiceChannel(sequelize);
@ -27,6 +34,7 @@ const Role = defineRole(sequelize);
Role.hasMany(RoleEmojiPair, { foreignKey: 'role', onDelete: 'CASCADE' });
const Guild = defineGuild(sequelize);
Guild.hasMany(Keyword, { foreignKey: 'guild', onDelete: 'CASCADE' });
Guild.hasMany(VoiceChannel, { foreignKey: 'guild', onDelete: 'CASCADE' });
Guild.hasMany(Message, { foreignKey: 'guild', onDelete: 'CASCADE' });
Guild.hasMany(Role, { foreignKey: 'guild', onDelete: 'CASCADE' });

View File

@ -3,16 +3,11 @@ import { DataTypes, Sequelize } from 'sequelize';
/**
* @typedef {Object} Guild
* @property {string} id A Discord guild ID.
* @property {(model: Object) => void} hasMany Defines an One-To-Many relationship.
* @property {(conditions: Object) => Promise<Guild>} findOne Finds one instance in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<Array<Guild>>} findAll Finds all instances in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<Guild>} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values.
*/
/**
* The definition of the `Guild` table in the database.
* @param {Sequelize} sequelize
* @returns {Guild}
*/
export default function (sequelize) {
return sequelize.define('Guilds', {

33
models/keywords.js Normal file
View File

@ -0,0 +1,33 @@
import { DataTypes, Deferrable, Sequelize } from 'sequelize';
/**
* @typedef {Object} Keyword
* @property {string} id A universally unique id, generated by sequelize.
* @property {string} guild A Discord guild ID as a foreign key reference.
* @property {string} name The name of the keyword.
*/
/**
* The definition of the `Keyword` table in the database.
* @param {Sequelize} sequelize
*/
export default function (sequelize) {
return sequelize.define('Keywords', {
id: {
defaultValue: DataTypes.UUIDV4,
type: DataTypes.UUID,
primaryKey: true
},
guild: {
type: DataTypes.STRING,
references: {
deferrable: Deferrable.INITIALLY_IMMEDIATE,
model: 'Guilds',
key: 'id'
}
},
name: {
type: DataTypes.STRING
}
});
}

View File

@ -4,16 +4,11 @@ import { DataTypes, Deferrable, Sequelize } from 'sequelize';
* @typedef {Object} Message
* @property {string} id A Discord message ID.
* @property {string} guild A Discord guild ID as a foreign key reference.
* @property {(model: Object) => void} hasMany Defines an One-To-Many relationship.
* @property {(conditions: Object) => Promise<Message>} findOne Finds one instance in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<Array<Message>>} findAll Finds all instances in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<Message>} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values.
*/
/**
* The definition of the `Message` table in the database.
* @param {Sequelize} sequelize
* @returns {Message}
*/
export default function (sequelize) {
return sequelize.define('Messages', {

37
models/responses.js Normal file
View File

@ -0,0 +1,37 @@
import { DataTypes, Deferrable, Sequelize } from 'sequelize';
/**
* @typedef {Object} Response
* @property {string} id A universally unique id, generated by sequelize.
* @property {string} keyword A universally unique id referencing a `Keyword`.
* @property {string} name The name of the response.
* @property {string} response The response data itself.
*/
/**
* The definition of the `Response` table in the database.
* @param {Sequelize} sequelize
*/
export default function (sequelize) {
return sequelize.define('Responses', {
id: {
defaultValue: DataTypes.UUIDV4,
type: DataTypes.UUID,
primaryKey: true
},
keyword: {
type: DataTypes.UUID,
references: {
deferrable: Deferrable.INITIALLY_IMMEDIATE,
model: 'Keywords',
key: 'id'
}
},
name: {
type: DataTypes.STRING
},
response: {
type: DataTypes.STRING
}
});
}

View File

@ -6,16 +6,11 @@ import { DataTypes, Deferrable, Sequelize } from 'sequelize';
* @property {string} message A Discord message ID as a foreign key reference.
* @property {string} role A Discord role ID.
* @property {string} emoji Either a unicode emoji or a string representation in Discord custom emoji format.
* @property {(model: Object) => void} hasMany Defines an One-To-Many relationship.
* @property {(conditions: Object) => Promise<RoleEmojiPair>} findOne Finds one instance in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<Array<RoleEmojiPair>>} findAll Finds all instances in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<RoleEmojiPair>} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values.
*/
/**
* The definition of the `RoleEmojiPair` table in the database.
* @param {Sequelize} sequelize
* @returns {RoleEmojiPair}
*/
export default function (sequelize) {
return sequelize.define('RoleEmojiPairs', {

View File

@ -5,16 +5,11 @@ import { DataTypes, Deferrable, Sequelize } from 'sequelize';
* @property {string} id A Discord role ID.
* @property {boolean} assign Whether or not the role should be assigned to new members.
* @property {string} guild A Discord guild ID as a foreign key reference.
* @property {(model: Object) => void} hasMany Defines an One-To-Many relationship.
* @property {(conditions: Object) => Promise<Role>} findOne Finds one instance in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<Array<Role>>} findAll Finds all instances in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<Role>} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values.
*/
/**
* The definition of the `Role` table in the database.
* @param {Sequelize} sequelize
* @returns {Role}
*/
export default function (sequelize) {
return sequelize.define('Roles', {

View File

@ -6,16 +6,11 @@ import { DataTypes, Deferrable, Sequelize } from 'sequelize';
* @property {boolean} create Whether or not this channel is registered to create customs when joined.
* @property {(string|null)} owner The owner of this channel, if not registered for customs.
* @property {string} guild A Discord guild ID as a foreign key reference.
* @property {(model: Object) => void} hasMany Defines an One-To-Many relationship.
* @property {(conditions: Object) => Promise<VoiceChannel>} findOne Finds one instance in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<Array<VoiceChannel>>} findAll Finds all instances in the database matching the provided condition(-s).
* @property {(conditions: Object) => Promise<VoiceChannel>} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values.
*/
/**
* The definition of the `VoiceChannel` table in the database.
* @param {Sequelize} sequelize
* @returns {VoiceChannel}
*/
export default function (sequelize) {
return sequelize.define('VoiceChannels', {