unhardcode self-assignable role stuff
this is pretty old stuff and i'm glad i revamped it bc it's a very good system
This commit is contained in:
parent
b6e92b2a52
commit
319f586565
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* @param { import("knex").Knex } knex
|
||||
* @returns { Promise<void> }
|
||||
*/
|
||||
exports.up = function(knex) {
|
||||
return knex.schema
|
||||
.createTable('roleSeperators', table => {
|
||||
table.string('guild');
|
||||
table.string('role');
|
||||
table.enum('type', ['color', 'pronoun']);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param { import("knex").Knex } knex
|
||||
* @returns { Promise<void> }
|
||||
*/
|
||||
exports.down = function(knex) {
|
||||
return knex.schema
|
||||
.dropTable('roleSeperators');
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
import { RoleCreateOptions, GuildMember, CommandInteraction, EmbedBuilder, TextChannel, ActionRowBuilder, ButtonBuilder, ButtonStyle, SlashCommandBuilder } from 'discord.js';
|
||||
import { default as parseColor, Color } from 'parse-color';
|
||||
import { isColorRole, COLOR_ROLE_SEPERATOR } from '../lib/assignableRoles';
|
||||
import { getRoleSeperator, isColorRole } from '../lib/assignableRoles';
|
||||
import * as log from '../lib/log';
|
||||
import { Command } from '../types/index';
|
||||
|
||||
|
@ -17,8 +17,8 @@ function removeAllColorRoles(member: GuildMember) {
|
|||
async function applyColor(member: GuildMember, color: Color) {
|
||||
await removeAllColorRoles(member);
|
||||
|
||||
const colorRoleSeperator = await member.guild.roles.fetch(COLOR_ROLE_SEPERATOR);
|
||||
if (!colorRoleSeperator) log.error('no color role seperator found?!?!');
|
||||
const seperator = await getRoleSeperator('color', member.guild);
|
||||
if (!seperator) log.info('no color role seperator found');
|
||||
|
||||
const roleSettings: RoleCreateOptions = {
|
||||
name: color.hex,
|
||||
|
@ -27,8 +27,8 @@ async function applyColor(member: GuildMember, color: Color) {
|
|||
mentionable: false,
|
||||
permissions: 0n,
|
||||
};
|
||||
if (colorRoleSeperator) {
|
||||
roleSettings.position = colorRoleSeperator.position;
|
||||
if (seperator) {
|
||||
roleSettings.position = seperator.position;
|
||||
}
|
||||
|
||||
const role = member.guild.roles.cache.find(role => role.name === color.hex) || await member.guild.roles.create(roleSettings);
|
||||
|
@ -46,7 +46,8 @@ export default {
|
|||
.addBooleanOption((option) =>
|
||||
option.setName('preview').setDescription('Preview the color instead of applying it')
|
||||
)
|
||||
.setDefaultMemberPermissions(0),
|
||||
.setDefaultMemberPermissions(0)
|
||||
.setDMPermission(false),
|
||||
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Guild, GuildMember, CommandInteraction, Role, SlashCommandBuilder } from 'discord.js';
|
||||
import { Guild, CommandInteraction, Role, SlashCommandBuilder } from 'discord.js';
|
||||
import { isColorRole, isPronounRole } from '../lib/assignableRoles';
|
||||
import { knownServers } from '../lib/knownServers';
|
||||
import { Command } from '../types/index';
|
||||
|
||||
async function fetchRoleMembers(role: Role) {
|
||||
|
@ -25,11 +24,10 @@ async function garbageCollectRoles(guild: Guild, dryRun: boolean): Promise<Role[
|
|||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('garbage-collect-roles')
|
||||
.setDescription('Garbage collect unused roles for colors and pronouns.')
|
||||
.addBooleanOption((option) => option.setName('dry-run').setDescription('Only show roles that would be deleted.'))
|
||||
.setDefaultMemberPermissions('0'),
|
||||
|
||||
serverWhitelist: [...knownServers.firepit],
|
||||
.setDescription('[ADMIN] Garbage collect unused self-assignable roles')
|
||||
.addBooleanOption((option) => option.setName('dry-run').setDescription('Only show roles that would be deleted'))
|
||||
.setDefaultMemberPermissions(0)
|
||||
.setDMPermission(false),
|
||||
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { RoleCreateOptions, GuildMember, CommandInteraction, SlashCommandBuilder } from 'discord.js';
|
||||
import { pronouns, PRONOUN_ROLE_SEPERATOR } from '../lib/assignableRoles';
|
||||
import { getRoleSeperator, pronouns } from '../lib/assignableRoles';
|
||||
import * as log from '../lib/log';
|
||||
import { Command } from '../types/index';
|
||||
|
||||
|
@ -18,7 +18,8 @@ export default {
|
|||
.setRequired(true)
|
||||
.setChoices(...Array.from(pronouns.values()).map(extendOption))
|
||||
)
|
||||
.setDefaultMemberPermissions(0),
|
||||
.setDefaultMemberPermissions(0)
|
||||
.setDMPermission(false),
|
||||
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
@ -31,8 +32,8 @@ export default {
|
|||
|
||||
const pronoun = interaction.options.getString('pronoun', true);
|
||||
|
||||
const pronounRoleSeperator = await member.guild.roles.fetch(PRONOUN_ROLE_SEPERATOR);
|
||||
if (!pronounRoleSeperator) log.error('no pronoun role seperator found?!?!');
|
||||
const seperator = await getRoleSeperator('color', member.guild);
|
||||
if (!seperator) log.info('no color role seperator found');
|
||||
|
||||
const roleSettings: RoleCreateOptions = {
|
||||
name: pronoun,
|
||||
|
@ -40,8 +41,8 @@ export default {
|
|||
mentionable: false,
|
||||
permissions: 0n
|
||||
};
|
||||
if (pronounRoleSeperator) {
|
||||
roleSettings.position = pronounRoleSeperator.position;
|
||||
if (seperator) {
|
||||
roleSettings.position = seperator.position;
|
||||
}
|
||||
|
||||
const pronounRole = member.guild.roles.cache.find(role => role.name === pronoun) || await member.guild.roles.create(roleSettings);
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
import { GuildMember, CommandInteraction, SlashCommandBuilder } from 'discord.js';
|
||||
import { Command } from '../types/index';
|
||||
import { RoleSeperator, RoleSeperatorType, db } from '../lib/db';
|
||||
|
||||
function extendOption(t: string) {
|
||||
return {name: t, value: t};
|
||||
}
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('roles')
|
||||
.setDescription('[ADMIN] Manage self-assignable roles')
|
||||
.addSubcommand(sub =>
|
||||
sub
|
||||
.setName('seperator')
|
||||
.setDescription('[ADMIN] Determine where new roles will be created')
|
||||
.addStringOption(opt =>
|
||||
opt
|
||||
.setName('type')
|
||||
.setDescription('The type of self-assignable role')
|
||||
.setChoices(...['color', 'pronoun'].map(extendOption))
|
||||
.setRequired(true)
|
||||
)
|
||||
.addRoleOption(opt =>
|
||||
opt
|
||||
.setName('seperator')
|
||||
.setDescription('Roles will be put *below* this role; omit to put them at the bottom of the wole list')
|
||||
)
|
||||
)
|
||||
.setDefaultMemberPermissions(0)
|
||||
.setDMPermission(false),
|
||||
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
const member = interaction.member! as GuildMember;
|
||||
|
||||
await interaction.deferReply({
|
||||
ephemeral: true
|
||||
});
|
||||
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
|
||||
if (subcommand === 'seperator') {
|
||||
const type = interaction.options.getString('type', true) as RoleSeperatorType;
|
||||
const seperator = interaction.options.getRole('seperator');
|
||||
|
||||
if (seperator) {
|
||||
const highestRole = member.guild.members.me!.roles.highest;
|
||||
|
||||
if (seperator.position > highestRole.position)
|
||||
return interaction.followUp(`This role is above my highest role (${highestRole.toString()}), so I can\`t put roles up there!`);
|
||||
|
||||
await db<RoleSeperator>('roleSeperators')
|
||||
.insert({
|
||||
guild: member.guild.id,
|
||||
type,
|
||||
role: seperator.id,
|
||||
});
|
||||
|
||||
await interaction.followUp(`New ${type} roles will be placed below ${seperator.toString()}.`);
|
||||
} else {
|
||||
const role = await db<RoleSeperator>('roleSeperators')
|
||||
.where('guild', member.guild.id)
|
||||
.where('type', type)
|
||||
.returning('*')
|
||||
.delete();
|
||||
|
||||
if (role === 0) {
|
||||
await interaction.followUp(`\`${type}\` never had a seperator role in this server!`);
|
||||
} else {
|
||||
await interaction.followUp(`Unset seperator role for \`${type}\`. Roles will now be placed at the bottom of the role list.`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
} satisfies Command;
|
|
@ -1,5 +1,5 @@
|
|||
export const COLOR_ROLE_SEPERATOR = '997893394850381834'; // put color roles below this role
|
||||
export const PRONOUN_ROLE_SEPERATOR = '997893842961440779'; // put pronoun roles below this role
|
||||
import { Guild } from 'discord.js';
|
||||
import { RoleSeperator, RoleSeperatorType, db } from './db';
|
||||
|
||||
export const pronouns = new Set([
|
||||
'he/him',
|
||||
|
@ -19,4 +19,15 @@ export function isColorRole(name: string) {
|
|||
|
||||
export function isPronounRole(name: string) {
|
||||
return pronouns.has(name);
|
||||
}
|
||||
|
||||
export async function getRoleSeperator(type: RoleSeperatorType, guild: Guild) {
|
||||
const seperator = await db<RoleSeperator>('roleSeperators')
|
||||
.select('role')
|
||||
.where('guild', guild.id)
|
||||
.where('type', type)
|
||||
.first();
|
||||
|
||||
if (seperator) return await guild.roles.fetch(seperator.role);
|
||||
return null;
|
||||
}
|
|
@ -96,4 +96,10 @@ export interface ItemBehavior {
|
|||
item: number,
|
||||
behavior: string,
|
||||
value?: number
|
||||
}
|
||||
export type RoleSeperatorType = 'color' | 'pronoun';
|
||||
export interface RoleSeperator {
|
||||
guild: string,
|
||||
role: string,
|
||||
type: RoleSeperatorType,
|
||||
}
|
Loading…
Reference in New Issue