v3.0.2 (#159)
* Change lobby command to error upon making a duplicate lobby channel (#154) * Update lobby command to give proper errors if role or channel id cannot be found (#156) * Add bunny command back (#157) * 150 assignable roles should be its own table to prevent limitations on length (#158) * Add entity * Update role config command to use new entity * Update role command to use new entity * Remove legacy code from config command * Update .env template to current date
This commit is contained in:
parent
31866b1c3b
commit
aa070bb7a7
10 changed files with 188 additions and 52 deletions
|
@ -7,7 +7,7 @@
|
||||||
# any secret values.
|
# any secret values.
|
||||||
|
|
||||||
BOT_TOKEN=
|
BOT_TOKEN=
|
||||||
BOT_VER=3.0.1
|
BOT_VER=3.0.2
|
||||||
BOT_AUTHOR=Vylpes
|
BOT_AUTHOR=Vylpes
|
||||||
BOT_DATE=24 Apr 2022
|
BOT_DATE=16 May 2022
|
||||||
BOT_OWNERID=147392775707426816
|
BOT_OWNERID=147392775707426816
|
|
@ -5,7 +5,6 @@ bot.prefix: The bot prefix for the server (Default: "v!")
|
||||||
|
|
||||||
commands.disabled: Disabled commands, separated by commas (Default: "")
|
commands.disabled: Disabled commands, separated by commas (Default: "")
|
||||||
|
|
||||||
role.assignable: List of roles assignable to user, separated by commas (Default: "")
|
|
||||||
role.moderator: The moderator role name (Default: "Moderator")
|
role.moderator: The moderator role name (Default: "Moderator")
|
||||||
role.administrator: The administrator role name (Default: "Administrator")
|
role.administrator: The administrator role name (Default: "Administrator")
|
||||||
role.muted: The muted role name (Default: "Muted")
|
role.muted: The muted role name (Default: "Muted")
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "node ./dist/vylbot",
|
"start": "node ./dist/vylbot",
|
||||||
"test": "jest"
|
"test": "jest",
|
||||||
|
"db:up": "typeorm migration:run",
|
||||||
|
"db:down": "typeorm migration:revert"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -111,8 +111,26 @@ export default class Lobby extends Command {
|
||||||
const cooldown = Number(context.args[4]) || 30;
|
const cooldown = Number(context.args[4]) || 30;
|
||||||
const gameName = context.args.splice(5).join(" ");
|
const gameName = context.args.splice(5).join(" ");
|
||||||
|
|
||||||
if (!channel || !role) {
|
if (!channel) {
|
||||||
this.SendConfigHelp(context);
|
const errorEmbed = new ErrorEmbed(context, "The channel id you provided is invalid or channel does not exist.");
|
||||||
|
errorEmbed.SendToCurrentChannel();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!role) {
|
||||||
|
const errorEmbed = new ErrorEmbed(context, "The role id you provided is invalid or role does not exist.");
|
||||||
|
errorEmbed.SendToCurrentChannel();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lobby = await eLobby.FetchOneByChannelId(channel.id);
|
||||||
|
|
||||||
|
if (lobby) {
|
||||||
|
const errorEmbed = new ErrorEmbed(context, "This channel has already been setup.");
|
||||||
|
errorEmbed.SendToCurrentChannel();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,20 +142,18 @@ export default class Lobby extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async RemoveLobbyConfig(context: ICommandContext) {
|
private async RemoveLobbyConfig(context: ICommandContext) {
|
||||||
const channel = context.message.guild!.channels.cache.find(x => x.id == context.args[2]);
|
const entity = await eLobby.FetchOneByChannelId(context.args[2]);
|
||||||
|
|
||||||
|
if (!entity) {
|
||||||
|
const errorEmbed = new ErrorEmbed(context, "The channel id you provided has not been setup as a lobby, unable to remove.");
|
||||||
|
errorEmbed.SendToCurrentChannel();
|
||||||
|
|
||||||
if (!channel) {
|
|
||||||
this.SendConfigHelp(context);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const entity = await eLobby.FetchOneByChannelId(channel.id);
|
await BaseEntity.Remove<eLobby>(eLobby, entity);
|
||||||
|
|
||||||
if (entity) {
|
const embed = new PublicEmbed(context, "", `Removed <#${context.args[2]}> from the list of lobby channels`);
|
||||||
await BaseEntity.Remove<eLobby>(eLobby, entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
const embed = new PublicEmbed(context, "", `Removed \`${channel.name}\` from the list of lobby channels`);
|
|
||||||
embed.SendToCurrentChannel();
|
embed.SendToCurrentChannel();
|
||||||
}
|
}
|
||||||
}
|
}
|
29
src/commands/bunny.ts
Normal file
29
src/commands/bunny.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import ErrorEmbed from "../helpers/embeds/ErrorEmbed";
|
||||||
|
import PublicEmbed from "../helpers/embeds/PublicEmbed";
|
||||||
|
import { Command } from "../type/command";
|
||||||
|
import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
|
import randomBunny from "random-bunny";
|
||||||
|
|
||||||
|
export default class Bunny extends Command {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
super.Category = "Fun";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async execute(context: ICommandContext) {
|
||||||
|
const result = await randomBunny('rabbits', 'hot');
|
||||||
|
|
||||||
|
if (result.IsSuccess) {
|
||||||
|
const embed = new PublicEmbed(context, result.Result!.Title, "")
|
||||||
|
.setImage(result.Result!.Url)
|
||||||
|
.setURL(`https://reddit.com${result.Result!.Permalink}`)
|
||||||
|
.setFooter({ text: `r/Rabbits · ${result.Result!.Ups} upvotes` });
|
||||||
|
|
||||||
|
embed.SendToCurrentChannel();
|
||||||
|
} else {
|
||||||
|
const errorEmbed = new ErrorEmbed(context, "There was an error using this command.");
|
||||||
|
errorEmbed.SendToCurrentChannel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,9 @@ import { ICommandContext } from "../contracts/ICommandContext";
|
||||||
import ICommandReturnContext from "../contracts/ICommandReturnContext";
|
import ICommandReturnContext from "../contracts/ICommandReturnContext";
|
||||||
import SettingsHelper from "../helpers/SettingsHelper";
|
import SettingsHelper from "../helpers/SettingsHelper";
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
|
import { default as eRole } from "../entity/Role";
|
||||||
|
import Server from "../entity/Server";
|
||||||
|
|
||||||
export default class Role extends Command {
|
export default class Role extends Command {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -30,27 +33,34 @@ export default class Role extends Command {
|
||||||
// =======
|
// =======
|
||||||
|
|
||||||
private async UseDefault(context: ICommandContext) {
|
private async UseDefault(context: ICommandContext) {
|
||||||
const roles = await SettingsHelper.GetSetting("role.assignable", context.message.guild!.id);
|
|
||||||
|
|
||||||
if (!roles) {
|
|
||||||
const errorEmbed = new ErrorEmbed(context, "Unable to find any assignable roles");
|
|
||||||
errorEmbed.SendToCurrentChannel();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rolesArray = roles.split(",");
|
|
||||||
|
|
||||||
if (context.args.length == 0) {
|
if (context.args.length == 0) {
|
||||||
await this.SendRolesList(context, rolesArray, context.message.guild!.id);
|
await this.SendRolesList(context, context.message.guild!.id);
|
||||||
} else {
|
} else {
|
||||||
await this.ToggleRole(context, rolesArray);
|
await this.ToggleRole(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async SendRolesList(context: ICommandContext, roles: String[], serverId: string): Promise<ICommandReturnContext> {
|
public async GetRolesList(context: ICommandContext): Promise<string[]> {
|
||||||
|
const rolesArray = await eRole.FetchAllByServerId(context.message.guild!.id);
|
||||||
|
|
||||||
|
const stringArray: string[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < rolesArray.length; i++) {
|
||||||
|
const serverRole = context.message.guild!.roles.cache.find(x => x.id == rolesArray[i].RoleId);
|
||||||
|
|
||||||
|
if (serverRole) {
|
||||||
|
stringArray.push(serverRole.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async SendRolesList(context: ICommandContext, serverId: string): Promise<ICommandReturnContext> {
|
||||||
|
const roles = await this.GetRolesList(context);
|
||||||
|
|
||||||
const botPrefix = await SettingsHelper.GetServerPrefix(serverId);
|
const botPrefix = await SettingsHelper.GetServerPrefix(serverId);
|
||||||
const description = `Do ${botPrefix}role <role> to get the role!\n${roles.join('\n')}`;
|
const description = roles.length == 0 ? "*no roles*" : `Do ${botPrefix}role <role> to get the role!\n\n${roles.join('\n')}`;
|
||||||
|
|
||||||
const embed = new PublicEmbed(context, "Roles", description);
|
const embed = new PublicEmbed(context, "Roles", description);
|
||||||
embed.SendToCurrentChannel();
|
embed.SendToCurrentChannel();
|
||||||
|
@ -61,7 +71,8 @@ export default class Role extends Command {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ToggleRole(context: ICommandContext, roles: String[]): Promise<ICommandReturnContext> {
|
public async ToggleRole(context: ICommandContext): Promise<ICommandReturnContext> {
|
||||||
|
const roles = await this.GetRolesList(context);
|
||||||
const requestedRole = context.args.join(" ");
|
const requestedRole = context.args.join(" ");
|
||||||
|
|
||||||
if (!roles.includes(requestedRole)) {
|
if (!roles.includes(requestedRole)) {
|
||||||
|
@ -165,15 +176,32 @@ export default class Role extends Command {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let setting = await SettingsHelper.GetSetting("role.assignable", context.message.guild!.id) || "";
|
const existingRole = await eRole.FetchOneByRoleId(role.id);
|
||||||
|
|
||||||
const settingArray = setting.split(",");
|
if (existingRole) {
|
||||||
|
const errorEmbed = new ErrorEmbed(context, "This role has already been setup");
|
||||||
|
errorEmbed.SendToCurrentChannel();
|
||||||
|
|
||||||
settingArray.push(role.name);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setting = settingArray.join(",");
|
const server = await Server.FetchOneById(Server, context.message.guild!.id, [
|
||||||
|
"Roles",
|
||||||
|
]);
|
||||||
|
|
||||||
await SettingsHelper.SetSetting("role.assignable", context.message.guild!.id, setting);
|
if (!server) {
|
||||||
|
const errorEmbed = new ErrorEmbed(context, "Server not setup, please request the server owner runs the setup command.");
|
||||||
|
errorEmbed.SendToCurrentChannel();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const roleSetting = new eRole(role.id);
|
||||||
|
|
||||||
|
await roleSetting.Save(eRole, roleSetting);
|
||||||
|
|
||||||
|
server.AddRoleToServer(roleSetting);
|
||||||
|
await server.Save(Server, server);
|
||||||
|
|
||||||
const embed = new PublicEmbed(context, "", `Added \`${role.name}\` as a new assignable role`);
|
const embed = new PublicEmbed(context, "", `Added \`${role.name}\` as a new assignable role`);
|
||||||
embed.SendToCurrentChannel();
|
embed.SendToCurrentChannel();
|
||||||
|
@ -187,21 +215,16 @@ export default class Role extends Command {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let setting = await SettingsHelper.GetSetting("role.assignable", context.message.guild!.id);
|
const existingRole = await eRole.FetchOneByRoleId(role.id);
|
||||||
|
|
||||||
if (!setting) return;
|
if (!existingRole) {
|
||||||
|
const errorEmbed = new ErrorEmbed(context, "Unable to find this role");
|
||||||
|
errorEmbed.SendToCurrentChannel();
|
||||||
|
|
||||||
const settingArray = setting.split(",");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const index = settingArray.findIndex(x => x == role.name);
|
await eRole.Remove(eRole, existingRole);
|
||||||
|
|
||||||
if (index == -1) return;
|
|
||||||
|
|
||||||
settingArray.splice(index, 1);
|
|
||||||
|
|
||||||
setting = settingArray.join(",");
|
|
||||||
|
|
||||||
await SettingsHelper.SetSetting("role.assignable", context.message.guild!.id, setting);
|
|
||||||
|
|
||||||
const embed = new PublicEmbed(context, "", `Removed \`${role.name}\` from the list of assignable roles`);
|
const embed = new PublicEmbed(context, "", `Removed \`${role.name}\` from the list of assignable roles`);
|
||||||
embed.SendToCurrentChannel();
|
embed.SendToCurrentChannel();
|
||||||
|
|
44
src/entity/Role.ts
Normal file
44
src/entity/Role.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { Column, Entity, EntityTarget, getConnection, ManyToOne } from "typeorm";
|
||||||
|
import BaseEntity from "../contracts/BaseEntity"
|
||||||
|
import Server from "./Server";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export default class Role extends BaseEntity {
|
||||||
|
constructor(roleId: string) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.RoleId = roleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
RoleId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => Server, x => x.Roles)
|
||||||
|
Server: Server;
|
||||||
|
|
||||||
|
public static async FetchOneByRoleId(roleId: string, relations?: string[]): Promise<Role | undefined> {
|
||||||
|
const connection = getConnection();
|
||||||
|
|
||||||
|
const repository = connection.getRepository(Role);
|
||||||
|
|
||||||
|
const single = await repository.findOne({ RoleId: roleId}, { relations: relations || [] });
|
||||||
|
|
||||||
|
return single;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async FetchAllByServerId(serverId: string): Promise<Role[]> {
|
||||||
|
const connection = getConnection();
|
||||||
|
|
||||||
|
const repository = connection.getRepository(Server);
|
||||||
|
|
||||||
|
const all = await repository.findOne(serverId, { relations: [
|
||||||
|
"Roles",
|
||||||
|
]});
|
||||||
|
|
||||||
|
if (!all) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return all.Roles;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import { Column, Entity, getConnection, OneToMany } from "typeorm";
|
import { Entity, OneToMany } from "typeorm";
|
||||||
import BaseEntity from "../contracts/BaseEntity";
|
import BaseEntity from "../contracts/BaseEntity";
|
||||||
|
import Role from "./Role";
|
||||||
import Setting from "./Setting";
|
import Setting from "./Setting";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
|
@ -13,7 +14,14 @@ export default class Server extends BaseEntity {
|
||||||
@OneToMany(() => Setting, x => x.Server)
|
@OneToMany(() => Setting, x => x.Server)
|
||||||
Settings: Setting[];
|
Settings: Setting[];
|
||||||
|
|
||||||
|
@OneToMany(() => Role, x => x.Server)
|
||||||
|
Roles: Role[];
|
||||||
|
|
||||||
public AddSettingToServer(setting: Setting) {
|
public AddSettingToServer(setting: Setting) {
|
||||||
this.Settings.push(setting);
|
this.Settings.push(setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AddRoleToServer(role: Role) {
|
||||||
|
this.Roles.push(role);
|
||||||
|
}
|
||||||
}
|
}
|
13
src/migration/1652375907691-CreateRole.ts
Normal file
13
src/migration/1652375907691-CreateRole.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||||
|
|
||||||
|
export class migration1652375907691 implements MigrationInterface {
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
queryRunner.query(`CREATE TABLE role (Id varchar(255), WhenCreated datetime, WhenUpdated datetime, RoleId varchar(255), serverId varchar(255), PRIMARY KEY (Id), FOREIGN KEY (serverId) REFERENCES server(Id))`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
queryRunner.query(`DROP TABLE role`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,11 +24,13 @@ import Lobby from "./commands/501231711271780357/lobby";
|
||||||
// Event Imports
|
// Event Imports
|
||||||
import MemberEvents from "./events/MemberEvents";
|
import MemberEvents from "./events/MemberEvents";
|
||||||
import MessageEvents from "./events/MessageEvents";
|
import MessageEvents from "./events/MessageEvents";
|
||||||
|
import Bunny from "./commands/bunny";
|
||||||
|
|
||||||
export default class Registry {
|
export default class Registry {
|
||||||
public static RegisterCommands() {
|
public static RegisterCommands() {
|
||||||
CoreClient.RegisterCommand("about", new About());
|
CoreClient.RegisterCommand("about", new About());
|
||||||
CoreClient.RegisterCommand("ban", new Ban());
|
CoreClient.RegisterCommand("ban", new Ban());
|
||||||
|
CoreClient.RegisterCommand("bunny", new Bunny());
|
||||||
CoreClient.RegisterCommand("clear", new Clear());
|
CoreClient.RegisterCommand("clear", new Clear());
|
||||||
CoreClient.RegisterCommand("help", new Help());
|
CoreClient.RegisterCommand("help", new Help());
|
||||||
CoreClient.RegisterCommand("kick", new Kick());
|
CoreClient.RegisterCommand("kick", new Kick());
|
||||||
|
|
Loading…
Reference in a new issue