mirror of
https://github.com/keanuplayz/TravBot-v3.git
synced 2024-08-15 02:33:12 +00:00
Various small changes/fixes
This commit is contained in:
parent
53705e76c5
commit
139630ce9f
11 changed files with 57 additions and 74 deletions
|
@ -2,6 +2,8 @@ import Command from "../core/command";
|
|||
import {CommonLibrary, logs} from "../core/lib";
|
||||
import {Config, Storage} from "../core/structures";
|
||||
import {PermissionNames, getPermissionLevel} from "../core/permissions";
|
||||
import {botHasPermission} from "../index";
|
||||
import {Permissions} from "discord.js";
|
||||
|
||||
function getLogBuffer(type: string)
|
||||
{
|
||||
|
@ -11,12 +13,7 @@ function getLogBuffer(type: string)
|
|||
}]};
|
||||
}
|
||||
|
||||
const activities: { [type: string]: string } = {
|
||||
playing: "",
|
||||
listening: "",
|
||||
streaming: "",
|
||||
watching: ""
|
||||
};
|
||||
const activities = ["playing", "listening", "streaming", "watching"];
|
||||
|
||||
export default new Command({
|
||||
description: "An all-in-one command to do admin stuff. You need to be either an admin of the server or one of the bot's mechanics to use this command.",
|
||||
|
@ -63,7 +60,7 @@ export default new Command({
|
|||
$.channel.send(getLogBuffer("info"));
|
||||
},
|
||||
any: new Command({
|
||||
description: `Select a verbosity to listen to. Available levels: \`[${Object.keys(logs)}]\``,
|
||||
description: `Select a verbosity to listen to. Available levels: \`[${Object.keys(logs).join(", ")}]\``,
|
||||
async run($: CommonLibrary): Promise<any>
|
||||
{
|
||||
const type = $.args[0];
|
||||
|
@ -71,7 +68,7 @@ export default new Command({
|
|||
if(type in logs)
|
||||
$.channel.send(getLogBuffer(type));
|
||||
else
|
||||
$.channel.send(`Couldn't find a verbosity level named \`${type}\`! The available types are \`[${Object.keys(logs)}]\`.`);
|
||||
$.channel.send(`Couldn't find a verbosity level named \`${type}\`! The available types are \`[${Object.keys(logs).join(", ")}]\`.`);
|
||||
}
|
||||
})
|
||||
}),
|
||||
|
@ -118,16 +115,13 @@ export default new Command({
|
|||
permission: Command.PERMISSIONS.BOT_SUPPORT,
|
||||
async run($: CommonLibrary): Promise<any>
|
||||
{
|
||||
try {
|
||||
const nickName = $.args.join(" ");
|
||||
const trav = $.guild?.members.cache.find(member => member.id === $.client.user?.id);
|
||||
await trav?.setNickname(nickName);
|
||||
$.message.delete({timeout: 5000});
|
||||
if(botHasPermission($.guild, Permissions.FLAGS.MANAGE_MESSAGES))
|
||||
$.message.delete({timeout: 5000}).catch($.handler.bind($));
|
||||
$.channel.send(`Nickname set to \`${nickName}\``)
|
||||
.then(m => m.delete({timeout: 5000}));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}),
|
||||
guilds: new Command({
|
||||
|
@ -152,17 +146,17 @@ export default new Command({
|
|||
$.channel.send("Activity set to default.")
|
||||
},
|
||||
any: new Command({
|
||||
description: `Select an activity type to set. Available levels: \`[${Object.keys(activities)}]\``,
|
||||
description: `Select an activity type to set. Available levels: \`[${activities.join(", ")}]\``,
|
||||
async run($: CommonLibrary): Promise<any>
|
||||
{
|
||||
const type = $.args[0];
|
||||
|
||||
if(type in activities) {
|
||||
if(activities.includes(type)) {
|
||||
$.client.user?.setActivity($.args.slice(1).join(" "), {type: $.args[0].toUpperCase()})
|
||||
$.channel.send(`Set activity to \`${$.args[0].toUpperCase()}\` \`${$.args.slice(1).join(" ")}\`.`)
|
||||
}
|
||||
else
|
||||
$.channel.send(`Couldn't find an activity type named \`${type}\`! The available types are \`[${Object.keys(activities)}]\`.`);
|
||||
$.channel.send(`Couldn't find an activity type named \`${type}\`! The available types are \`[${activities.join(", ")}]\`.`);
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -41,7 +41,7 @@ export default new Command({
|
|||
async run($: CommonLibrary): Promise<any>
|
||||
{
|
||||
const sender = $.message.author;
|
||||
$.channel.send(responses[Math.floor(Math.random() * responses.length)] + ` <@${sender.id}>`);
|
||||
$.channel.send($(responses).random() + ` <@${sender.id}>`);
|
||||
}
|
||||
})
|
||||
}),
|
||||
|
|
|
@ -6,7 +6,7 @@ import { verificationLevels, filterLevels, regions, flags } from "../defs/info";
|
|||
|
||||
export default new Command({
|
||||
description: "Command to provide all sorts of info about the current server, a user, etc.",
|
||||
run: "Please provide an argument.\nFor help, run `.help info`.",
|
||||
run: "Please provide an argument.\nFor help, run `%prefix%help info`.",
|
||||
subcommands:
|
||||
{
|
||||
avatar: new Command({
|
||||
|
|
|
@ -1,34 +1,31 @@
|
|||
import {Client} from "discord.js";
|
||||
import {Client, ClientEvents, Constants} from "discord.js";
|
||||
import Storage from "./storage";
|
||||
import $ from "./lib";
|
||||
|
||||
// Last Updated: Discord.js v12.2.0
|
||||
const EVENTS = ["channelCreate", "channelDelete", "channelPinsUpdate", "channelUpdate", "debug", "warn", "disconnect", "emojiCreate", "emojiDelete", "emojiUpdate", "error", "guildBanAdd", "guildBanRemove", "guildCreate", "guildDelete", "guildUnavailable", "guildIntegrationsUpdate", "guildMemberAdd", "guildMemberAvailable", "guildMemberRemove", "guildMembersChunk", "guildMemberSpeaking", "guildMemberUpdate", "guildUpdate", "inviteCreate", "inviteDelete", "message", "messageDelete", "messageReactionRemoveAll", "messageReactionRemoveEmoji", "messageDeleteBulk", "messageReactionAdd", "messageReactionRemove", "messageUpdate", "presenceUpdate", "rateLimit", "ready", "invalidated", "roleCreate", "roleDelete", "roleUpdate", "typingStart", "userUpdate", "voiceStateUpdate", "webhookUpdate", "shardDisconnect", "shardError", "shardReady", "shardReconnecting", "shardResume"];
|
||||
|
||||
interface EventOptions
|
||||
interface EventOptions<K extends keyof ClientEvents>
|
||||
{
|
||||
readonly on?: Function;
|
||||
readonly once?: Function;
|
||||
readonly on?: (...args: ClientEvents[K]) => void;
|
||||
readonly once?: (...args: ClientEvents[K]) => void;
|
||||
}
|
||||
|
||||
export default class Event
|
||||
export default class Event<K extends keyof ClientEvents>
|
||||
{
|
||||
private readonly on: Function|null;
|
||||
private readonly once: Function|null;
|
||||
private readonly on?: (...args: ClientEvents[K]) => void;
|
||||
private readonly once?: (...args: ClientEvents[K]) => void;
|
||||
|
||||
constructor(options: EventOptions)
|
||||
constructor(options: EventOptions<K>)
|
||||
{
|
||||
this.on = options.on || null;
|
||||
this.once = options.once || null;
|
||||
this.on = options.on;
|
||||
this.once = options.once;
|
||||
}
|
||||
|
||||
// For this function, I'm going to assume that the event is used with the correct arguments and that the event tag is checked in "storage.ts".
|
||||
public attach(client: Client, event: string)
|
||||
public attach(client: Client, event: K)
|
||||
{
|
||||
if(this.on)
|
||||
client.on(event as any, this.on as any);
|
||||
client.on(event, this.on);
|
||||
if(this.once)
|
||||
client.once(event as any, this.once as any);
|
||||
client.once(event, this.once);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +36,7 @@ export async function loadEvents(client: Client)
|
|||
const header = file.substring(0, file.indexOf(".js"));
|
||||
const event = (await import(`../events/${header}`)).default;
|
||||
|
||||
if(EVENTS.includes(header))
|
||||
if((Object.values(Constants.Events) as string[]).includes(header))
|
||||
{
|
||||
event.attach(client, header);
|
||||
$.log(`Loading Event: ${header}`);
|
||||
|
|
|
@ -3,7 +3,7 @@ import {Client, Message, TextChannel, DMChannel, NewsChannel, Guild, User, Guild
|
|||
import chalk from "chalk";
|
||||
import FileManager from "./storage";
|
||||
import {eventListeners} from "../events/messageReactionRemove";
|
||||
import {client} from "../index";
|
||||
import {botHasPermission} from "../index";
|
||||
|
||||
/** A type that describes what the library module does. */
|
||||
export interface CommonLibrary
|
||||
|
@ -170,10 +170,10 @@ $.paginate = async(message: Message, senderID: string, total: number, callback:
|
|||
await message.awaitReactions((reaction, user) => {
|
||||
// The reason this is inside the call is because it's possible to switch a user's permissions halfway and suddenly throw an error.
|
||||
// This will dynamically adjust for that, switching modes depending on whether it currently has the "Manage Messages" permission.
|
||||
const canDeleteEmotes = !!(client.user && message.guild?.members.resolve(client.user)?.hasPermission(Permissions.FLAGS.MANAGE_MESSAGES));
|
||||
const canDeleteEmotes = botHasPermission(message.guild, Permissions.FLAGS.MANAGE_MESSAGES);
|
||||
handle(reaction.emoji.name, user.id);
|
||||
|
||||
if(canDeleteEmotes && user.id !== client.user?.id)
|
||||
if(canDeleteEmotes)
|
||||
reaction.users.remove(user);
|
||||
|
||||
return false;
|
||||
|
@ -258,7 +258,7 @@ export function parseArgs(line: string): string[]
|
|||
* - `%%` = `%`
|
||||
* - If the invalid token is null/undefined, nothing is changed.
|
||||
*/
|
||||
export function parseVars(line: string, definitions: {[key: string]: string}, invalid: string|null|undefined = ""): string
|
||||
export function parseVars(line: string, definitions: {[key: string]: string}, invalid: string|null = ""): string
|
||||
{
|
||||
let result = "";
|
||||
let inVariable = false;
|
||||
|
@ -276,7 +276,7 @@ export function parseVars(line: string, definitions: {[key: string]: string}, in
|
|||
{
|
||||
if(token in definitions)
|
||||
result += definitions[token];
|
||||
else if(invalid === undefined || invalid === null)
|
||||
else if(invalid === null)
|
||||
result += `%${token}%`;
|
||||
else
|
||||
result += invalid;
|
||||
|
@ -352,7 +352,7 @@ export interface GenericJSON
|
|||
|
||||
export abstract class GenericStructure
|
||||
{
|
||||
protected __meta__ = "generic";
|
||||
private __meta__ = "generic";
|
||||
|
||||
constructor(tag?: string)
|
||||
{
|
||||
|
|
|
@ -38,30 +38,17 @@ const length = Object.keys(PERMISSIONS).length / 2;
|
|||
|
||||
export function hasPermission(member: GuildMember, permission: PERMISSIONS): boolean
|
||||
{
|
||||
if(permission === PERMISSIONS.NONE)
|
||||
return true;
|
||||
|
||||
for(let i = length-1; i >= permission; i--)
|
||||
{
|
||||
const condition = PermissionChecker[i](member);
|
||||
|
||||
if(condition)
|
||||
if(PermissionChecker[i](member))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getPermissionLevel(member: GuildMember): number
|
||||
{
|
||||
for(let i = length-1; i >= 0; i--)
|
||||
{
|
||||
const condition = PermissionChecker[i](member);
|
||||
|
||||
if(condition)
|
||||
if(PermissionChecker[i](member))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import Event from "../core/event";
|
||||
import Command, {loadCommands} from "../core/command";
|
||||
import {hasPermission, getPermissionLevel, PermissionNames} from "../core/permissions";
|
||||
import $ from "../core/lib";
|
||||
import {Message, Permissions, Collection} from "discord.js";
|
||||
import {Permissions, Collection} from "discord.js";
|
||||
import {getPrefix} from "../core/structures";
|
||||
import $ from "../core/lib";
|
||||
|
||||
// It's a rather hacky solution, but since there's no top-level await, I just have to make the loading conditional.
|
||||
let commands: Collection<string, Command>|null = null;
|
||||
|
||||
export default new Event({
|
||||
async on(message: Message)
|
||||
export default new Event<"message">({
|
||||
async on(message)
|
||||
{
|
||||
// Load commands if it hasn't already done so. Luckily, it's called once at most.
|
||||
if(!commands)
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import Event from "../core/event";
|
||||
import {MessageReaction, User, PartialUser, Permissions} from "discord.js";
|
||||
import {client} from "../index";
|
||||
import {Permissions} from "discord.js";
|
||||
import {botHasPermission} from "../index";
|
||||
|
||||
// A list of message ID and callback pairs. You get the emote name and ID of the user reacting.
|
||||
export const eventListeners: Map<string, (emote: string, id: string) => void> = new Map();
|
||||
|
||||
// Attached to the client, there can be one event listener attached to a message ID which is executed if present.
|
||||
export default new Event({
|
||||
on(reaction: MessageReaction, user: User|PartialUser)
|
||||
export default new Event<"messageReactionRemove">({
|
||||
on(reaction, user)
|
||||
{
|
||||
const canDeleteEmotes = !!(client.user && reaction.message.guild?.members.resolve(client.user)?.hasPermission(Permissions.FLAGS.MANAGE_MESSAGES));
|
||||
const canDeleteEmotes = botHasPermission(reaction.message.guild, Permissions.FLAGS.MANAGE_MESSAGES);
|
||||
|
||||
if(!canDeleteEmotes)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@ import {client} from "../index";
|
|||
import $ from "../core/lib";
|
||||
import {Config} from "../core/structures";
|
||||
|
||||
export default new Event({
|
||||
export default new Event<"ready">({
|
||||
once()
|
||||
{
|
||||
if(client.user)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {Client} from "discord.js";
|
||||
import {Client, Guild} from "discord.js";
|
||||
import setup from "./setup";
|
||||
import {Config} from "./core/structures";
|
||||
import {loadCommands} from "./core/command";
|
||||
|
@ -14,3 +14,8 @@ setup.init().then(() => {
|
|||
loadEvents(client);
|
||||
client.login(Config.token).catch(setup.again);
|
||||
});
|
||||
|
||||
export function botHasPermission(guild: Guild|null, permission: number): boolean
|
||||
{
|
||||
return !!(client.user && guild?.members.resolve(client.user)?.hasPermission(permission))
|
||||
}
|
|
@ -44,7 +44,7 @@ export default {
|
|||
Config.admins = admins !== "" ? admins.split(" ") : [];
|
||||
const support = (answers.support as string);
|
||||
Config.support = support !== "" ? support.split(" ") : [];
|
||||
Config.save();
|
||||
Config.save(false);
|
||||
}
|
||||
},
|
||||
/** Prompt the user to set their token again. */
|
||||
|
|
Loading…
Reference in a new issue