Separated custom logger from command menu

This commit is contained in:
WatDuhHekBro 2021-03-30 03:58:21 -05:00
parent 00addd468c
commit 10c1cd9cff
24 changed files with 6763 additions and 1388 deletions

7794
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,10 @@
import Command from "../core/command";
import {CommonLibrary, logs, botHasPermission, clean} from "../core/lib";
import {CommonLibrary, botHasPermission, clean} from "../core/lib";
import {Config, Storage} from "../core/structures";
import {PermissionNames, getPermissionLevel} from "../core/permissions";
import {Permissions} from "discord.js";
import * as discord from "discord.js";
import {logs} from "../globals";
function getLogBuffer(type: string) {
return {

View File

@ -62,7 +62,7 @@ export function getSendEmbed(sender: User, receiver: User, amount: number): obje
}
export function isAuthorized(guild: Guild | null, channel: TextChannel | DMChannel | NewsChannel): boolean {
if (guild?.id === "637512823676600330" && channel?.id === "669464416420364288" || process.argv[2] === "dev") return true;
if ((guild?.id === "637512823676600330" && channel?.id === "669464416420364288") || IS_DEV_MODE) return true;
else {
channel.send("Sorry, this command can only be used in Monika's emote server. (#mon-stocks)");
return false;

View File

@ -19,7 +19,9 @@ export default new Command({
const command = commands.get(header);
if (!command)
return $.warn(`Command "${header}" of category "${category}" unexpectedly doesn't exist!`);
return console.warn(
`Command "${header}" of category "${category}" unexpectedly doesn't exist!`
);
output += `\n- \`${header}\`: ${command.description}`;
}
@ -37,7 +39,7 @@ export default new Command({
if (!command || header === "test") return $.channel.send(`No command found by the name \`${header}\`!`);
if (command.originalCommandName) header = command.originalCommandName;
else $.warn(`originalCommandName isn't defined for ${header}?!`);
else console.warn(`originalCommandName isn't defined for ${header}?!`);
let permLevel = command.permission ?? Command.PERMISSIONS.NONE;
let usage = command.usage;
@ -48,7 +50,7 @@ export default new Command({
for (const [category, headers] of categories) {
if (headers.includes(header)) {
if (selectedCategory !== "Unknown")
$.warn(
console.warn(
`Command "${header}" is somehow in multiple categories. This means that the command loading stage probably failed in properly adding categories.`
);
else selectedCategory = $(category).toTitleCase();

View File

@ -131,7 +131,7 @@ export default new Command({
continueReactionLoop = false;
if (reaction.count !== userReactions + botReactions) {
$.warn(
console.warn(
`[Channel: ${channel.id}, Message: ${msg.id}] A reaction count of ${reaction.count} was expected but was given ${userReactions} user reactions and ${botReactions} bot reactions.`
);
warnings++;
@ -161,7 +161,7 @@ export default new Command({
"y"
)}.`
);
$.log(`Finished operation in ${finishTime - startTime} ms.`);
console.log(`Finished operation in ${finishTime - startTime} ms.`);
$.channel.stopTyping();
// Display stats on emote usage.

View File

@ -1,4 +1,4 @@
import $, {isType, parseVars, CommonLibrary} from "./lib";
import {isType, parseVars, CommonLibrary} from "./lib";
import {Collection} from "discord.js";
import {PERMISSIONS} from "./permissions";
import {getPrefix} from "../core/structures";
@ -68,11 +68,11 @@ export default class Command {
for (const alias of aliases) {
if (baseSubcommands.includes(alias))
$.warn(
console.warn(
`"${alias}" in subcommand "${name}" was attempted to be declared as an alias but it already exists in the base commands! (Look at the next "Loading Command" line to see which command is affected.)`
);
else if (this.subcommands.has(alias))
$.warn(
console.warn(
`Duplicate alias "${alias}" at subcommand "${name}"! (Look at the next "Loading Command" line to see which command is affected.)`
);
else this.subcommands.set(alias, subcmd);
@ -81,17 +81,17 @@ export default class Command {
}
if (this.user && this.user.aliases.length > 0)
$.warn(
console.warn(
`There are aliases defined for a "user"-type subcommand, but those aliases won't be used. (Look at the next "Loading Command" line to see which command is affected.)`
);
if (this.number && this.number.aliases.length > 0)
$.warn(
console.warn(
`There are aliases defined for a "number"-type subcommand, but those aliases won't be used. (Look at the next "Loading Command" line to see which command is affected.)`
);
if (this.any && this.any.aliases.length > 0)
$.warn(
console.warn(
`There are aliases defined for an "any"-type subcommand, but those aliases won't be used. (Look at the next "Loading Command" line to see which command is affected.)`
);
}
@ -179,7 +179,7 @@ export const loadableCommands = (async () => {
command.originalCommandName = commandName;
if (commands.has(commandName)) {
$.warn(
console.warn(
`Command "${commandName}" already exists! Make sure to make each command uniquely identifiable across categories!`
);
} else {
@ -188,7 +188,7 @@ export const loadableCommands = (async () => {
for (const alias of command.aliases) {
if (commands.has(alias)) {
$.warn(
console.warn(
`Top-level alias "${alias}" from command "${commandID}" already exists either as a command or alias!`
);
} else {
@ -199,9 +199,9 @@ export const loadableCommands = (async () => {
if (!(category in lists)) lists[category] = [];
lists[category].push(commandName);
$.log(`Loading Command: ${commandID}`);
console.log(`Loading Command: ${commandID}`);
} else {
$.warn(`Command "${commandID}" has no default export which is a Command instance!`);
console.warn(`Command "${commandID}" has no default export which is a Command instance!`);
}
}
}

View File

@ -1,6 +1,5 @@
import {Client, ClientEvents, Constants} from "discord.js";
import Storage from "./storage";
import $ from "./lib";
interface EventOptions<K extends keyof ClientEvents> {
readonly on?: (...args: ClientEvents[K]) => void;
@ -30,9 +29,9 @@ export async function loadEvents(client: Client) {
if ((Object.values(Constants.Events) as string[]).includes(header)) {
event.attach(client, header);
$.log(`Loading Event: ${header}`);
console.log(`Loading Event: ${header}`);
} else
$.warn(
console.warn(
`"${header}" is not a valid event type! Did you misspell it? (Note: If you fixed the issue, delete "dist" because the compiler won't automatically delete any extra files.)`
);
}

View File

@ -1,6 +1,5 @@
import {GenericWrapper, NumberWrapper, StringWrapper, ArrayWrapper} from "./wrappers";
import {Client, Message, TextChannel, DMChannel, NewsChannel, Guild, User, GuildMember, Permissions} from "discord.js";
import chalk from "chalk";
import {get} from "https";
import FileManager from "./storage";
import {eventListeners} from "../events/messageReactionRemove";
@ -19,11 +18,6 @@ export interface CommonLibrary {
// Common Library Functions //
/** <Promise>.catch($.handler.bind($)) or <Promise>.catch(error => $.handler(error)) */
handler: (error: Error) => void;
log: (...args: any[]) => void;
warn: (...args: any[]) => void;
error: (...args: any[]) => void;
debug: (...args: any[]) => void;
ready: (...args: any[]) => void;
paginate: (
message: Message,
senderID: string,
@ -79,94 +73,13 @@ $.handler = function (this: CommonLibrary, error: Error) {
`There was an error while trying to execute that command!\`\`\`${error.stack ?? error}\`\`\``
);
else
$.warn(
console.warn(
"No context was attached to $.handler! Make sure to use .catch($.handler.bind($)) or .catch(error => $.handler(error)) instead!"
);
$.error(error);
console.error(error);
};
// Logs with different levels of verbosity.
export const logs: {[type: string]: string} = {
error: "",
warn: "",
info: "",
verbose: ""
};
let enabled = true;
export function setConsoleActivated(activated: boolean) {
enabled = activated;
}
// The custom console. In order of verbosity, error, warn, log, and debug. Ready is a variation of log.
// General Purpose Logger
$.log = (...args: any[]) => {
if (enabled) console.log(chalk.white.bgGray(formatTimestamp()), chalk.black.bgWhite("INFO"), ...args);
const text = `[${formatUTCTimestamp()}] [INFO] ${args.join(" ")}\n`;
logs.info += text;
logs.verbose += text;
};
// "It'll still work, but you should really check up on this."
$.warn = (...args: any[]) => {
if (enabled) console.warn(chalk.white.bgGray(formatTimestamp()), chalk.black.bgYellow("WARN"), ...args);
const text = `[${formatUTCTimestamp()}] [WARN] ${args.join(" ")}\n`;
logs.warn += text;
logs.info += text;
logs.verbose += text;
};
// Used for anything which prevents the program from actually running.
$.error = (...args: any[]) => {
if (enabled) console.error(chalk.white.bgGray(formatTimestamp()), chalk.white.bgRed("ERROR"), ...args);
const text = `[${formatUTCTimestamp()}] [ERROR] ${args.join(" ")}\n`;
logs.error += text;
logs.warn += text;
logs.info += text;
logs.verbose += text;
};
// Be as verbose as possible. If anything might help when debugging an error, then include it. This only shows in your console if you run this with "dev", but you can still get it from "logs.verbose".
// $.debug(`core/lib::parseArgs("testing \"in progress\"") = ["testing", "in progress"]`) --> <path>/::(<object>.)<function>(<args>) = <value>
// Would probably be more suited for debugging program logic rather than function logic, which can be checked using unit tests.
$.debug = (...args: any[]) => {
if (process.argv[2] === "dev" && enabled)
console.debug(chalk.white.bgGray(formatTimestamp()), chalk.white.bgBlue("DEBUG"), ...args);
const text = `[${formatUTCTimestamp()}] [DEBUG] ${args.join(" ")}\n`;
logs.verbose += text;
};
// Used once at the start of the program when the bot loads.
$.ready = (...args: any[]) => {
if (enabled) console.log(chalk.white.bgGray(formatTimestamp()), chalk.black.bgGreen("READY"), ...args);
const text = `[${formatUTCTimestamp()}] [READY] ${args.join(" ")}\n`;
logs.info += text;
logs.verbose += text;
};
export function formatTimestamp(now = new Date()) {
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, "0");
const day = now.getDate().toString().padStart(2, "0");
const hour = now.getHours().toString().padStart(2, "0");
const minute = now.getMinutes().toString().padStart(2, "0");
const second = now.getSeconds().toString().padStart(2, "0");
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
export function formatUTCTimestamp(now = new Date()) {
const year = now.getUTCFullYear();
const month = (now.getUTCMonth() + 1).toString().padStart(2, "0");
const day = now.getUTCDate().toString().padStart(2, "0");
const hour = now.getUTCHours().toString().padStart(2, "0");
const minute = now.getUTCMinutes().toString().padStart(2, "0");
const second = now.getUTCSeconds().toString().padStart(2, "0");
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
export function botHasPermission(guild: Guild | null, permission: number): boolean {
return !!guild?.me?.hasPermission(permission);
}

View File

@ -1,6 +1,5 @@
import {GuildMember, Permissions} from "discord.js";
import {Config} from "./structures";
import $ from "./lib";
export enum PERMISSIONS {
NONE,
@ -70,7 +69,7 @@ export function getPermissionLevel(member: GuildMember): number {
// By transitive property, lenNames and lenChecker have to be equal to each other as well.
if (length !== lenNames || length !== lenChecker)
$.error(
console.error(
`Permission object lengths aren't equal! Enum Length (${length}), Names Length (${lenNames}), and Functions Length (${lenChecker}). This WILL cause problems!`
);
})();

View File

@ -1,5 +1,4 @@
import fs from "fs";
import $ from "./lib";
const Storage = {
read(header: string): object {
@ -14,7 +13,7 @@ const Storage = {
data = JSON.parse(file);
} catch (error) {
if (process.argv[2] !== "dev") {
$.warn(`Malformed JSON data (header: ${header}), backing it up.`, file);
console.warn(`Malformed JSON data (header: ${header}), backing it up.`, file);
fs.writeFile(
`${path}.backup`,
file,
@ -30,7 +29,7 @@ const Storage = {
this.open("data");
const path = `data/${header}.json`;
if (process.argv[2] === "dev" || header === "config") {
if (IS_DEV_MODE || header === "config") {
const result = JSON.stringify(data, null, "\t");
if (asynchronous)
@ -60,8 +59,8 @@ const Storage = {
export function generateHandler(message: string) {
return (error: Error | null) => {
if (error) $.error(error);
else $.debug(message);
if (error) console.error(error);
else console.debug(message);
};
}

View File

@ -1,5 +1,5 @@
import FileManager from "./storage";
import $, {select, GenericJSON, GenericStructure} from "./lib";
import {select, GenericJSON, GenericStructure} from "./lib";
import {watch} from "fs";
import {Guild as DiscordGuild, Snowflake} from "discord.js";
@ -63,7 +63,7 @@ class StorageStructure extends GenericStructure {
/** Gets a user's profile if they exist and generate one if not. */
public getUser(id: string): User {
if (!/\d{17,19}/g.test(id))
$.warn(`"${id}" is not a valid user ID! It will be erased when the data loads again.`);
console.warn(`"${id}" is not a valid user ID! It will be erased when the data loads again.`);
if (id in this.users) return this.users[id];
else {
@ -76,7 +76,7 @@ class StorageStructure extends GenericStructure {
/** Gets a guild's settings if they exist and generate one if not. */
public getGuild(id: string): Guild {
if (!/\d{17,19}/g.test(id))
$.warn(`"${id}" is not a valid guild ID! It will be erased when the data loads again.`);
console.warn(`"${id}" is not a valid guild ID! It will be erased when the data loads again.`);
if (id in this.guilds) return this.guilds[id];
else {
@ -93,9 +93,9 @@ export let Storage = new StorageStructure(FileManager.read("storage"));
// This part will allow the user to manually edit any JSON files they want while the program is running which'll update the program's cache.
// However, fs.watch is a buggy mess that should be avoided in production. While it helps test out stuff for development, it's not a good idea to have it running outside of development as it causes all sorts of issues.
if (process.argv[2] === "dev") {
if (IS_DEV_MODE) {
watch("data", (event, filename) => {
$.debug("File Watcher:", event, filename);
console.debug("File Watcher:", event, filename);
const header = filename.substring(0, filename.indexOf(".json"));
switch (header) {

View File

@ -1,6 +1,5 @@
import Event from "../core/event";
import {client} from "../index";
import $ from "../core/lib";
import * as discord from "discord.js";
export default new Event<"channelCreate">({
@ -8,7 +7,7 @@ export default new Event<"channelCreate">({
const botGuilds = client.guilds;
if (channel instanceof discord.GuildChannel) {
const createdGuild = await botGuilds.fetch(channel.guild.id);
$.log(`Channel created in '${createdGuild.name}' called '#${channel.name}'`);
console.log(`Channel created in '${createdGuild.name}' called '#${channel.name}'`);
}
}
});

View File

@ -1,6 +1,5 @@
import Event from "../core/event";
import {client} from "../index";
import $ from "../core/lib";
import * as discord from "discord.js";
export default new Event<"channelDelete">({
@ -8,7 +7,7 @@ export default new Event<"channelDelete">({
const botGuilds = client.guilds;
if (channel instanceof discord.GuildChannel) {
const createdGuild = await botGuilds.fetch(channel.guild.id);
$.log(`Channel deleted in '${createdGuild.name}' called '#${channel.name}'`);
console.log(`Channel deleted in '${createdGuild.name}' called '#${channel.name}'`);
}
}
});

View File

@ -1,10 +1,9 @@
import Event from "../core/event";
import $ from "../core/lib";
import {updateGlobalEmoteRegistry} from "../core/lib";
export default new Event<"emojiCreate">({
on(emote) {
$.log(`Updated emote registry. ${emote.name}`);
console.log(`Updated emote registry. ${emote.name}`);
updateGlobalEmoteRegistry();
}
});

View File

@ -1,10 +1,9 @@
import Event from "../core/event";
import $ from "../core/lib";
import {updateGlobalEmoteRegistry} from "../core/lib";
export default new Event<"emojiDelete">({
on() {
$.log("Updated emote registry.");
console.log("Updated emote registry.");
updateGlobalEmoteRegistry();
}
});

View File

@ -1,10 +1,9 @@
import Event from "../core/event";
import $ from "../core/lib";
import {updateGlobalEmoteRegistry} from "../core/lib";
export default new Event<"emojiUpdate">({
on() {
$.log("Updated emote registry.");
console.log("Updated emote registry.");
updateGlobalEmoteRegistry();
}
});

View File

@ -1,10 +1,9 @@
import Event from "../core/event";
import $ from "../core/lib";
import {updateGlobalEmoteRegistry} from "../core/lib";
export default new Event<"guildCreate">({
on() {
$.log("Updated emote registry.");
console.log("Updated emote registry.");
updateGlobalEmoteRegistry();
}
});

View File

@ -1,10 +1,9 @@
import Event from "../core/event";
import $ from "../core/lib";
import {updateGlobalEmoteRegistry} from "../core/lib";
export default new Event<"guildDelete">({
on() {
$.log("Updated emote registry.");
console.log("Updated emote registry.");
updateGlobalEmoteRegistry();
}
});

View File

@ -82,13 +82,13 @@ export default new Event<"message">({
);
}
$.log(
console.log(
`${message.author.username}#${message.author.discriminator} executed the command "${header}" with arguments "${args}".`
);
// Subcommand Recursion //
let command = commands.get(header);
if (!command) return $.warn(`Command "${header}" was called but for some reason it's still undefined!`);
if (!command) return console.warn(`Command "${header}" was called but for some reason it's still undefined!`);
const params: any[] = [];
let isEndpoint = false;
let permLevel = command.permission ?? Command.PERMISSIONS.NONE;
@ -96,7 +96,7 @@ export default new Event<"message">({
for (let param of args) {
if (command.endpoint) {
if (command.subcommands.size > 0 || command.user || command.number || command.any)
$.warn(`An endpoint cannot have subcommands! Check ${originalPrefix}${header} again.`);
console.warn(`An endpoint cannot have subcommands! Check ${originalPrefix}${header} again.`);
isEndpoint = true;
break;
}
@ -117,7 +117,7 @@ export default new Event<"message">({
}
if (!message.member)
return $.warn("This command was likely called from a DM channel meaning the member object is null.");
return console.warn("This command was likely called from a DM channel meaning the member object is null.");
if (!hasPermission(message.member, permLevel)) {
const userPermLevel = getPermissionLevel(message.member);

View File

@ -1,13 +1,12 @@
import Event from "../core/event";
import {client} from "../index";
import $ from "../core/lib";
import {Config} from "../core/structures";
import {updateGlobalEmoteRegistry} from "../core/lib";
export default new Event<"ready">({
once() {
if (client.user) {
$.ready(`Logged in as ${client.user.username}#${client.user.discriminator}.`);
console.ready(`Logged in as ${client.user.username}#${client.user.discriminator}.`);
client.user.setActivity({
type: "LISTENING",
name: `${Config.prefix}help`

86
src/globals.ts Normal file
View File

@ -0,0 +1,86 @@
import chalk from "chalk";
declare global {
var IS_DEV_MODE: boolean;
interface Console {
ready: (...data: any[]) => void;
}
}
global.IS_DEV_MODE = process.argv[2] === "dev";
const oldConsole = console;
export const logs: {[type: string]: string} = {
error: "",
warn: "",
info: "",
verbose: ""
};
function formatTimestamp(now = new Date()) {
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, "0");
const day = now.getDate().toString().padStart(2, "0");
const hour = now.getHours().toString().padStart(2, "0");
const minute = now.getMinutes().toString().padStart(2, "0");
const second = now.getSeconds().toString().padStart(2, "0");
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
function formatUTCTimestamp(now = new Date()) {
const year = now.getUTCFullYear();
const month = (now.getUTCMonth() + 1).toString().padStart(2, "0");
const day = now.getUTCDate().toString().padStart(2, "0");
const hour = now.getUTCHours().toString().padStart(2, "0");
const minute = now.getUTCMinutes().toString().padStart(2, "0");
const second = now.getUTCSeconds().toString().padStart(2, "0");
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
// The custom console. In order of verbosity, error, warn, log, and debug. Ready is a variation of log.
console = {
...oldConsole,
// General Purpose Logger
log(...args: any[]) {
oldConsole.log(chalk.white.bgGray(formatTimestamp()), chalk.black.bgWhite("INFO"), ...args);
const text = `[${formatUTCTimestamp()}] [INFO] ${args.join(" ")}\n`;
logs.info += text;
logs.verbose += text;
},
// "It'll still work, but you should really check up on this."
warn(...args: any[]) {
oldConsole.warn(chalk.white.bgGray(formatTimestamp()), chalk.black.bgYellow("WARN"), ...args);
const text = `[${formatUTCTimestamp()}] [WARN] ${args.join(" ")}\n`;
logs.warn += text;
logs.info += text;
logs.verbose += text;
},
// Used for anything which prevents the program from actually running.
error(...args: any[]) {
oldConsole.error(chalk.white.bgGray(formatTimestamp()), chalk.white.bgRed("ERROR"), ...args);
const text = `[${formatUTCTimestamp()}] [ERROR] ${args.join(" ")}\n`;
logs.error += text;
logs.warn += text;
logs.info += text;
logs.verbose += text;
},
// Be as verbose as possible. If anything might help when debugging an error, then include it. This only shows in your console if you run this with "dev", but you can still get it from "logs.verbose".
// $.debug(`core/lib::parseArgs("testing \"in progress\"") = ["testing", "in progress"]`) --> <path>/::(<object>.)<function>(<args>) = <value>
// Would probably be more suited for debugging program logic rather than function logic, which can be checked using unit tests.
debug(...args: any[]) {
if (IS_DEV_MODE) oldConsole.debug(chalk.white.bgGray(formatTimestamp()), chalk.white.bgBlue("DEBUG"), ...args);
const text = `[${formatUTCTimestamp()}] [DEBUG] ${args.join(" ")}\n`;
logs.verbose += text;
},
// Used once at the start of the program when the bot loads.
ready(...args: any[]) {
oldConsole.log(chalk.white.bgGray(formatTimestamp()), chalk.black.bgGreen("READY"), ...args);
const text = `[${formatUTCTimestamp()}] [READY] ${args.join(" ")}\n`;
logs.info += text;
logs.verbose += text;
}
};
console.log("Loading globals...");

View File

@ -1,3 +1,4 @@
import "./globals";
import * as discord from "discord.js";
import setup from "./setup";
import {Config} from "./core/structures";

View File

@ -1,60 +1,61 @@
import { client } from '..'
import { Message, TextChannel, APIMessage, MessageEmbed } from 'discord.js'
import { getPrefix } from '../core/structures'
import { DiscordAPIError } from 'discord.js'
import {client} from "..";
import {Message, TextChannel, APIMessage, MessageEmbed} from "discord.js";
import {getPrefix} from "../core/structures";
import {DiscordAPIError} from "discord.js";
export default async function quote(message: Message) {
if (message.author.bot) return
if (message.author.bot) return;
// const message_link_regex = message.content.match(/(!)?https?:\/\/\w+\.com\/channels\/(\d+)\/(\d+)\/(\d+)/)
const message_link_regex = message.content.match(/([<!]?)https?:\/\/(?:ptb\.|canary\.|)discord(?:app)?\.com\/channels\/(\d+)\/(\d+)\/(\d+)(>?)/)
const message_link_regex = message.content.match(
/([<!]?)https?:\/\/(?:ptb\.|canary\.|)discord(?:app)?\.com\/channels\/(\d+)\/(\d+)\/(\d+)(>?)/
);
if (message_link_regex == null) return
const [, char, guildID, channelID, messageID] = message_link_regex
if (message_link_regex == null) return;
const [, char, guildID, channelID, messageID] = message_link_regex;
if (char || message.content.startsWith(getPrefix(message.guild))) return
if (char || message.content.startsWith(getPrefix(message.guild))) return;
try {
const channel = client.guilds.cache.get(guildID)?.channels.cache.get(channelID) as TextChannel
const link_message = await channel.messages.fetch(messageID)
const channel = client.guilds.cache.get(guildID)?.channels.cache.get(channelID) as TextChannel;
const link_message = await channel.messages.fetch(messageID);
let rtmsg: string | APIMessage = ''
let rtmsg: string | APIMessage = "";
if (link_message.cleanContent) {
rtmsg = new APIMessage(message.channel as TextChannel, {
content: link_message.cleanContent,
disableMentions: 'all',
disableMentions: "all",
files: link_message.attachments.array()
})
});
}
const embeds = [
...link_message.embeds.filter(v => v.type == 'rich'),
...link_message.attachments.values()
]
const embeds = [...link_message.embeds.filter((v) => v.type == "rich"), ...link_message.attachments.values()];
/// @ts-ignore
if (!link_message.cleanContent && embeds.empty) {
const Embed = new MessageEmbed()
.setDescription('🚫 The message is empty.')
return message.channel.send(Embed)
const Embed = new MessageEmbed().setDescription("🚫 The message is empty.");
return message.channel.send(Embed);
}
const infoEmbed = new MessageEmbed()
.setAuthor(
link_message.author.username,
link_message.author.displayAvatarURL({format: 'png', dynamic: true, size: 4096}))
link_message.author.displayAvatarURL({format: "png", dynamic: true, size: 4096})
)
.setTimestamp(link_message.createdTimestamp)
.setDescription(`${link_message.cleanContent}\n\nSent in **${link_message.guild?.name}** | <#${link_message.channel.id}> ([link](https://discord.com/channels/${guildID}/${channelID}/${messageID}))`);
if (link_message.attachments.size !== 0) {
const image = link_message.attachments.first();
/// @ts-ignore
infoEmbed.setImage(image.url);
}
.setDescription(
`${link_message.cleanContent}\n\nSent in **${link_message.guild?.name}** | <#${link_message.channel.id}> ([link](https://discord.com/channels/${guildID}/${channelID}/${messageID}))`
);
if (link_message.attachments.size !== 0) {
const image = link_message.attachments.first();
/// @ts-ignore
infoEmbed.setImage(image.url);
}
await message.channel.send(infoEmbed)
await message.channel.send(infoEmbed);
} catch (error) {
if (error instanceof DiscordAPIError) {
message.channel.send("I don't have access to this channel, or something else went wrong.")
message.channel.send("I don't have access to this channel, or something else went wrong.");
}
return console.error(error)
return console.error(error);
}
}
}

View File

@ -2,12 +2,11 @@ import {existsSync as exists, readFileSync as read, writeFile as write} from "fs
import inquirer from "inquirer";
import Storage, {generateHandler} from "./core/storage";
import {Config} from "./core/structures";
import $, {setConsoleActivated} from "./core/lib";
// The template should be built with a reductionist mentality.
// Provide everything the user needs and then let them remove whatever they want.
// That way, they aren't focusing on what's missing, but rather what they need for their command.
if (process.argv[2] === "dev" && !exists("src/commands/test.ts")) {
if (IS_DEV_MODE && !exists("src/commands/test.ts")) {
write(
"src/commands/test.ts",
read("src/commands/template.ts"),
@ -64,8 +63,19 @@ export default {
},
/** Prompt the user to set their token again. */
async again() {
$.error("It seems that the token you provided is invalid.");
setConsoleActivated(false);
console.error("It seems that the token you provided is invalid.");
// Deactivate the console //
const oldConsole = console;
console = {
...oldConsole,
log() {},
warn() {},
error() {},
debug() {},
ready() {}
};
const answers = await inquirer.prompt(prompts.slice(0, 1));
Config.token = answers.token as string;
Config.save(false);