mirror of
				https://github.com/keanuplayz/TravBot-v3.git
				synced 2024-08-15 02:33:12 +00:00 
			
		
		
		
	Added more library functions to command handler
This commit is contained in:
		
							parent
							
								
									bd67f3b8cc
								
							
						
					
					
						commit
						54ce28d8d4
					
				
					 8 changed files with 217 additions and 130 deletions
				
			
		|  | @ -1,9 +1,10 @@ | ||||||
| import {Command, NamedCommand, callMemberByUsername} from "../../core"; | import {Command, NamedCommand, getMemberByName} from "../../core"; | ||||||
| import {isAuthorized, getMoneyEmbed} from "./modules/eco-utils"; | import {isAuthorized, getMoneyEmbed} from "./modules/eco-utils"; | ||||||
| import {DailyCommand, PayCommand, GuildCommand, LeaderboardCommand} from "./modules/eco-core"; | import {DailyCommand, PayCommand, GuildCommand, LeaderboardCommand} from "./modules/eco-core"; | ||||||
| import {BuyCommand, ShopCommand} from "./modules/eco-shop"; | import {BuyCommand, ShopCommand} from "./modules/eco-shop"; | ||||||
| import {MondayCommand, AwardCommand} from "./modules/eco-extras"; | import {MondayCommand, AwardCommand} from "./modules/eco-extras"; | ||||||
| import {BetCommand} from "./modules/eco-bet"; | import {BetCommand} from "./modules/eco-bet"; | ||||||
|  | import {GuildMember} from "discord.js"; | ||||||
| 
 | 
 | ||||||
| export default new NamedCommand({ | export default new NamedCommand({ | ||||||
|     description: "Economy command for Monika.", |     description: "Economy command for Monika.", | ||||||
|  | @ -35,10 +36,11 @@ export default new NamedCommand({ | ||||||
|     any: new Command({ |     any: new Command({ | ||||||
|         description: "See how much money someone else has by using their username.", |         description: "See how much money someone else has by using their username.", | ||||||
|         async run({guild, channel, args, message}) { |         async run({guild, channel, args, message}) { | ||||||
|             if (isAuthorized(guild, channel)) |             if (isAuthorized(guild, channel)) { | ||||||
|                 callMemberByUsername(message, args.join(" "), (member) => { |                 const member = await getMemberByName(guild!, args.join(" ")); | ||||||
|                     channel.send(getMoneyEmbed(member.user)); |                 if (member instanceof GuildMember) channel.send(getMoneyEmbed(member.user)); | ||||||
|                 }); |                 else channel.send(member); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     }) |     }) | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import {User} from "discord.js"; | import {User, GuildMember} from "discord.js"; | ||||||
| import {Command, NamedCommand, getMemberByUsername, CHANNEL_TYPE} from "../../core"; | import {Command, NamedCommand, getMemberByName, CHANNEL_TYPE} from "../../core"; | ||||||
| 
 | 
 | ||||||
| // Quotes must be used here or the numbers will change
 | // Quotes must be used here or the numbers will change
 | ||||||
| const registry: {[id: string]: string} = { | const registry: {[id: string]: string} = { | ||||||
|  | @ -69,12 +69,10 @@ export default new NamedCommand({ | ||||||
|         channelType: CHANNEL_TYPE.GUILD, |         channelType: CHANNEL_TYPE.GUILD, | ||||||
|         async run({message, channel, guild, author, client, args}) { |         async run({message, channel, guild, author, client, args}) { | ||||||
|             const query = args.join(" ") as string; |             const query = args.join(" ") as string; | ||||||
|             const member = await getMemberByUsername(guild!, query); |             const member = await getMemberByName(guild!, query); | ||||||
| 
 | 
 | ||||||
|             if (member && member.id in registry) { |             if (member instanceof GuildMember) { | ||||||
|                 const id = member.id; |                 if (member.id in registry) { | ||||||
| 
 |  | ||||||
|                 if (id in registry) { |  | ||||||
|                     channel.send(`\`${member.nickname ?? member.user.username}\` - ${registry[member.id]}`); |                     channel.send(`\`${member.nickname ?? member.user.username}\` - ${registry[member.id]}`); | ||||||
|                 } else { |                 } else { | ||||||
|                     channel.send( |                     channel.send( | ||||||
|  | @ -82,7 +80,7 @@ export default new NamedCommand({ | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 channel.send(`Couldn't find a user by the name of \`${query}\`!`); |                 channel.send(member); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }) |     }) | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| import {MessageEmbed, version as djsversion, Guild, User, GuildMember} from "discord.js"; | import {MessageEmbed, version as djsversion, Guild, User, GuildMember} from "discord.js"; | ||||||
| import ms from "ms"; | import ms from "ms"; | ||||||
| import os from "os"; | import os from "os"; | ||||||
| import {Command, NamedCommand, getMemberByUsername, CHANNEL_TYPE} from "../../core"; | import {Command, NamedCommand, getMemberByName, CHANNEL_TYPE} from "../../core"; | ||||||
| import {formatBytes, trimArray} from "../../lib"; | import {formatBytes, trimArray} from "../../lib"; | ||||||
| import {verificationLevels, filterLevels, regions} from "../../defs/info"; | import {verificationLevels, filterLevels, regions} from "../../defs/info"; | ||||||
| import moment, {utc} from "moment"; | import moment, {utc} from "moment"; | ||||||
|  | @ -35,9 +35,9 @@ export default new NamedCommand({ | ||||||
|                 channelType: CHANNEL_TYPE.GUILD, |                 channelType: CHANNEL_TYPE.GUILD, | ||||||
|                 async run({message, channel, guild, author, client, args}) { |                 async run({message, channel, guild, author, client, args}) { | ||||||
|                     const name = args.join(" "); |                     const name = args.join(" "); | ||||||
|                     const member = await getMemberByUsername(guild!, name); |                     const member = await getMemberByName(guild!, name); | ||||||
| 
 | 
 | ||||||
|                     if (member) { |                     if (member instanceof GuildMember) { | ||||||
|                         channel.send( |                         channel.send( | ||||||
|                             member.user.displayAvatarURL({ |                             member.user.displayAvatarURL({ | ||||||
|                                 dynamic: true, |                                 dynamic: true, | ||||||
|  | @ -45,7 +45,7 @@ export default new NamedCommand({ | ||||||
|                             }) |                             }) | ||||||
|                         ); |                         ); | ||||||
|                     } else { |                     } else { | ||||||
|                         channel.send(`No user found by the name \`${name}\`!`); |                         channel.send(member); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             }) |             }) | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| import {Command, NamedCommand, ask, askYesOrNo, askMultipleChoice, prompt, callMemberByUsername} from "../../core"; | import {Command, NamedCommand, ask, askYesOrNo, askMultipleChoice, prompt, getMemberByName} from "../../core"; | ||||||
| import {Storage} from "../../structures"; | import {Storage} from "../../structures"; | ||||||
| import {User} from "discord.js"; | import {User, GuildMember} from "discord.js"; | ||||||
| import moment from "moment"; | import moment from "moment"; | ||||||
| 
 | 
 | ||||||
| const DATE_FORMAT = "D MMMM YYYY"; | const DATE_FORMAT = "D MMMM YYYY"; | ||||||
|  | @ -383,10 +383,10 @@ export default new NamedCommand({ | ||||||
|     }), |     }), | ||||||
|     any: new Command({ |     any: new Command({ | ||||||
|         description: "See what time it is for someone else (by their username).", |         description: "See what time it is for someone else (by their username).", | ||||||
|         async run({channel, args, message}) { |         async run({channel, args, guild}) { | ||||||
|             callMemberByUsername(message, args.join(" "), (member) => { |             const member = await getMemberByName(guild!, args.join(" ")); | ||||||
|                 channel.send(getTimeEmbed(member.user)); |             if (member instanceof GuildMember) channel.send(getTimeEmbed(member.user)); | ||||||
|             }); |             else channel.send(member); | ||||||
|         } |         } | ||||||
|     }) |     }) | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -8,9 +8,10 @@ import { | ||||||
|     Guild, |     Guild, | ||||||
|     User, |     User, | ||||||
|     GuildMember, |     GuildMember, | ||||||
|     GuildChannel |     GuildChannel, | ||||||
|  |     Channel | ||||||
| } from "discord.js"; | } from "discord.js"; | ||||||
| import {SingleMessageOptions} from "./libd"; | import {getChannelByID, getMessageByID, getUserByID, SingleMessageOptions} from "./libd"; | ||||||
| import {hasPermission, getPermissionLevel, getPermissionName} from "./permissions"; | import {hasPermission, getPermissionLevel, getPermissionName} from "./permissions"; | ||||||
| import {getPrefix} from "./interface"; | import {getPrefix} from "./interface"; | ||||||
| import {parseVars, requireAllCasesHandledFor} from "../lib"; | import {parseVars, requireAllCasesHandledFor} from "../lib"; | ||||||
|  | @ -338,17 +339,20 @@ export class Command { | ||||||
|             return this.subcommands.get(param)!.execute(args, menu, metadata); |             return this.subcommands.get(param)!.execute(args, menu, metadata); | ||||||
|         } else if (this.channel && patterns.channel.test(param)) { |         } else if (this.channel && patterns.channel.test(param)) { | ||||||
|             const id = patterns.channel.exec(param)![1]; |             const id = patterns.channel.exec(param)![1]; | ||||||
|             const channel = menu.client.channels.cache.get(id); |             const channel = await getChannelByID(id); | ||||||
| 
 | 
 | ||||||
|             // Users can only enter in this format for text channels, so this restricts it to that.
 |             if (channel instanceof Channel) { | ||||||
|             if (channel instanceof TextChannel) { |                 if (channel instanceof TextChannel || channel instanceof DMChannel) { | ||||||
|                 metadata.symbolicArgs.push("<channel>"); |                     metadata.symbolicArgs.push("<channel>"); | ||||||
|                 menu.args.push(channel); |                     menu.args.push(channel); | ||||||
|                 return this.channel.execute(args, menu, metadata); |                     return this.channel.execute(args, menu, metadata); | ||||||
|  |                 } else { | ||||||
|  |                     return { | ||||||
|  |                         content: `\`${id}\` is not a valid text channel!` | ||||||
|  |                     }; | ||||||
|  |                 } | ||||||
|             } else { |             } else { | ||||||
|                 return { |                 return channel; | ||||||
|                     content: `\`${id}\` is not a valid text channel!` |  | ||||||
|                 }; |  | ||||||
|             } |             } | ||||||
|         } else if (this.role && patterns.role.test(param)) { |         } else if (this.role && patterns.role.test(param)) { | ||||||
|             const id = patterns.role.exec(param)![1]; |             const id = patterns.role.exec(param)![1]; | ||||||
|  | @ -397,34 +401,25 @@ export class Command { | ||||||
|                 messageID = result[2]; |                 messageID = result[2]; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const channel = menu.client.channels.cache.get(channelID); |             const message = await getMessageByID(channelID, messageID); | ||||||
| 
 | 
 | ||||||
|             if (channel instanceof TextChannel || channel instanceof DMChannel) { |             if (message instanceof Message) { | ||||||
|                 try { |                 metadata.symbolicArgs.push("<message>"); | ||||||
|                     metadata.symbolicArgs.push("<message>"); |                 menu.args.push(message); | ||||||
|                     menu.args.push(await channel.messages.fetch(messageID)); |                 return this.message.execute(args, menu, metadata); | ||||||
|                     return this.message.execute(args, menu, metadata); |  | ||||||
|                 } catch { |  | ||||||
|                     return { |  | ||||||
|                         content: `\`${messageID}\` isn't a valid message of channel ${channel}!` |  | ||||||
|                     }; |  | ||||||
|                 } |  | ||||||
|             } else { |             } else { | ||||||
|                 return { |                 return message; | ||||||
|                     content: `\`${channelID}\` is not a valid text channel!` |  | ||||||
|                 }; |  | ||||||
|             } |             } | ||||||
|         } else if (this.user && patterns.user.test(param)) { |         } else if (this.user && patterns.user.test(param)) { | ||||||
|             const id = patterns.user.exec(param)![1]; |             const id = patterns.user.exec(param)![1]; | ||||||
|  |             const user = await getUserByID(id); | ||||||
| 
 | 
 | ||||||
|             try { |             if (user instanceof User) { | ||||||
|                 metadata.symbolicArgs.push("<user>"); |                 metadata.symbolicArgs.push("<user>"); | ||||||
|                 menu.args.push(await menu.client.users.fetch(id)); |                 menu.args.push(user); | ||||||
|                 return this.user.execute(args, menu, metadata); |                 return this.user.execute(args, menu, metadata); | ||||||
|             } catch { |             } else { | ||||||
|                 return { |                 return user; | ||||||
|                     content: `No user found by the ID \`${id}\`!` |  | ||||||
|                 }; |  | ||||||
|             } |             } | ||||||
|         } else if (this.id && this.idType && patterns.id.test(param)) { |         } else if (this.id && this.idType && patterns.id.test(param)) { | ||||||
|             metadata.symbolicArgs.push("<id>"); |             metadata.symbolicArgs.push("<id>"); | ||||||
|  | @ -434,16 +429,20 @@ export class Command { | ||||||
|             // Because this part is pretty much a whole bunch of copy pastes.
 |             // Because this part is pretty much a whole bunch of copy pastes.
 | ||||||
|             switch (this.idType) { |             switch (this.idType) { | ||||||
|                 case "channel": |                 case "channel": | ||||||
|                     const channel = menu.client.channels.cache.get(id); |                     const channel = await getChannelByID(id); | ||||||
| 
 | 
 | ||||||
|                     // Users can only enter in this format for text channels, so this restricts it to that.
 |                     if (channel instanceof Channel) { | ||||||
|                     if (channel instanceof TextChannel) { |                         if (channel instanceof TextChannel || channel instanceof DMChannel) { | ||||||
|                         menu.args.push(channel); |                             metadata.symbolicArgs.push("<channel>"); | ||||||
|                         return this.id.execute(args, menu, metadata); |                             menu.args.push(channel); | ||||||
|  |                             return this.id.execute(args, menu, metadata); | ||||||
|  |                         } else { | ||||||
|  |                             return { | ||||||
|  |                                 content: `\`${id}\` is not a valid text channel!` | ||||||
|  |                             }; | ||||||
|  |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         return { |                         return channel; | ||||||
|                             content: `\`${id}\` isn't a valid text channel!` |  | ||||||
|                         }; |  | ||||||
|                     } |                     } | ||||||
|                 case "role": |                 case "role": | ||||||
|                     if (!menu.guild) { |                     if (!menu.guild) { | ||||||
|  | @ -474,22 +473,22 @@ export class Command { | ||||||
|                         }; |                         }; | ||||||
|                     } |                     } | ||||||
|                 case "message": |                 case "message": | ||||||
|                     try { |                     const message = await getMessageByID(menu.channel, id); | ||||||
|                         menu.args.push(await menu.channel.messages.fetch(id)); | 
 | ||||||
|  |                     if (message instanceof Message) { | ||||||
|  |                         menu.args.push(message); | ||||||
|                         return this.id.execute(args, menu, metadata); |                         return this.id.execute(args, menu, metadata); | ||||||
|                     } catch { |                     } else { | ||||||
|                         return { |                         return message; | ||||||
|                             content: `\`${id}\` isn't a valid message of channel ${menu.channel}!` |  | ||||||
|                         }; |  | ||||||
|                     } |                     } | ||||||
|                 case "user": |                 case "user": | ||||||
|                     try { |                     const user = await getUserByID(id); | ||||||
|                         menu.args.push(await menu.client.users.fetch(id)); | 
 | ||||||
|  |                     if (user instanceof User) { | ||||||
|  |                         menu.args.push(user); | ||||||
|                         return this.id.execute(args, menu, metadata); |                         return this.id.execute(args, menu, metadata); | ||||||
|                     } catch { |                     } else { | ||||||
|                         return { |                         return user; | ||||||
|                             content: `No user found by the ID \`${id}\`!` |  | ||||||
|                         }; |  | ||||||
|                     } |                     } | ||||||
|                 default: |                 default: | ||||||
|                     requireAllCasesHandledFor(this.idType); |                     requireAllCasesHandledFor(this.idType); | ||||||
|  |  | ||||||
|  | @ -2,16 +2,6 @@ | ||||||
| export {Command, NamedCommand, CHANNEL_TYPE} from "./command"; | export {Command, NamedCommand, CHANNEL_TYPE} from "./command"; | ||||||
| export {addInterceptRule} from "./handler"; | export {addInterceptRule} from "./handler"; | ||||||
| export {launch} from "./interface"; | export {launch} from "./interface"; | ||||||
| export { | export * from "./libd"; | ||||||
|     SingleMessageOptions, |  | ||||||
|     botHasPermission, |  | ||||||
|     paginate, |  | ||||||
|     prompt, |  | ||||||
|     ask, |  | ||||||
|     askYesOrNo, |  | ||||||
|     askMultipleChoice, |  | ||||||
|     getMemberByUsername, |  | ||||||
|     callMemberByUsername |  | ||||||
| } from "./libd"; |  | ||||||
| export {getCommandList, getCommandInfo} from "./loader"; | export {getCommandList, getCommandInfo} from "./loader"; | ||||||
| export {hasPermission, getPermissionLevel, getPermissionName} from "./permissions"; | export {hasPermission, getPermissionLevel, getPermissionName} from "./permissions"; | ||||||
|  |  | ||||||
|  | @ -25,11 +25,13 @@ interface LaunchSettings { | ||||||
| // Additionally, each method would return the object so multiple methods could be chained, such as OnionCore.setPermissions(...).setPrefixResolver(...).launch(client).
 | // Additionally, each method would return the object so multiple methods could be chained, such as OnionCore.setPermissions(...).setPrefixResolver(...).launch(client).
 | ||||||
| // I decided to not do this because creating a class then having a bunch of boilerplate around it just wouldn't really be worth it.
 | // I decided to not do this because creating a class then having a bunch of boilerplate around it just wouldn't really be worth it.
 | ||||||
| // commandsDirectory requires an absolute path to work, so use __dirname.
 | // commandsDirectory requires an absolute path to work, so use __dirname.
 | ||||||
| export async function launch(client: Client, commandsDirectory: string, settings?: LaunchSettings) { | export async function launch(newClient: Client, commandsDirectory: string, settings?: LaunchSettings) { | ||||||
|     // Core Launch Parameters //
 |     // Core Launch Parameters //
 | ||||||
|  |     client.destroy(); // Release any resources/connections being used by the placeholder client.
 | ||||||
|  |     client = newClient; | ||||||
|     loadableCommands = loadCommands(commandsDirectory); |     loadableCommands = loadCommands(commandsDirectory); | ||||||
|     attachMessageHandlerToClient(client); |     attachMessageHandlerToClient(newClient); | ||||||
|     attachEventListenersToClient(client); |     attachEventListenersToClient(newClient); | ||||||
| 
 | 
 | ||||||
|     // Additional Configuration //
 |     // Additional Configuration //
 | ||||||
|     if (settings?.permissionLevels) { |     if (settings?.permissionLevels) { | ||||||
|  | @ -42,6 +44,7 @@ export async function launch(client: Client, commandsDirectory: string, settings | ||||||
| 
 | 
 | ||||||
| // Placeholder until properly loaded by the user.
 | // Placeholder until properly loaded by the user.
 | ||||||
| export let loadableCommands = (async () => new Collection<string, NamedCommand>())(); | export let loadableCommands = (async () => new Collection<string, NamedCommand>())(); | ||||||
|  | export let client = new Client(); | ||||||
| export let permissionLevels: PermissionLevel[] = [ | export let permissionLevels: PermissionLevel[] = [ | ||||||
|     { |     { | ||||||
|         name: "User", |         name: "User", | ||||||
|  |  | ||||||
							
								
								
									
										179
									
								
								src/core/libd.ts
									
										
									
									
									
								
							
							
						
						
									
										179
									
								
								src/core/libd.ts
									
										
									
									
									
								
							|  | @ -7,9 +7,13 @@ import { | ||||||
|     TextChannel, |     TextChannel, | ||||||
|     DMChannel, |     DMChannel, | ||||||
|     NewsChannel, |     NewsChannel, | ||||||
|     MessageOptions |     MessageOptions, | ||||||
|  |     Channel, | ||||||
|  |     GuildChannel, | ||||||
|  |     User | ||||||
| } from "discord.js"; | } from "discord.js"; | ||||||
| import {unreactEventListeners, replyEventListeners} from "./eventListeners"; | import {unreactEventListeners, replyEventListeners} from "./eventListeners"; | ||||||
|  | import {client} from "./interface"; | ||||||
| 
 | 
 | ||||||
| export type SingleMessageOptions = MessageOptions & {split?: false}; | export type SingleMessageOptions = MessageOptions & {split?: false}; | ||||||
| 
 | 
 | ||||||
|  | @ -20,16 +24,19 @@ export function botHasPermission(guild: Guild | null, permission: number): boole | ||||||
|     return !!guild?.me?.hasPermission(permission); |     return !!guild?.me?.hasPermission(permission); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // The SoonTM Section //
 | ||||||
| // Maybe promisify this section to reduce the potential for creating callback hell? Especially if multiple questions in a row are being asked.
 | // Maybe promisify this section to reduce the potential for creating callback hell? Especially if multiple questions in a row are being asked.
 | ||||||
| 
 | // It's probably a good idea to modularize the base reaction handler so there's less copy pasted code.
 | ||||||
| // Pagination function that allows for customization via a callback.
 | // Maybe also make a reaction handler that listens for when reactions are added and removed.
 | ||||||
| // Define your own pages outside the function because this only manages the actual turning of pages.
 | // The reaction handler would also run an async function to react in order (parallel to the reaction handler).
 | ||||||
| 
 | 
 | ||||||
| const FIVE_BACKWARDS_EMOJI = "⏪"; | const FIVE_BACKWARDS_EMOJI = "⏪"; | ||||||
| const BACKWARDS_EMOJI = "⬅️"; | const BACKWARDS_EMOJI = "⬅️"; | ||||||
| const FORWARDS_EMOJI = "➡️"; | const FORWARDS_EMOJI = "➡️"; | ||||||
| const FIVE_FORWARDS_EMOJI = "⏩"; | const FIVE_FORWARDS_EMOJI = "⏩"; | ||||||
| 
 | 
 | ||||||
|  | // Pagination function that allows for customization via a callback.
 | ||||||
|  | // Define your own pages outside the function because this only manages the actual turning of pages.
 | ||||||
| /** | /** | ||||||
|  * Takes a message and some additional parameters and makes a reaction page with it. All the pagination logic is taken care of but nothing more, the page index is returned and you have to send a callback to do something with it. |  * Takes a message and some additional parameters and makes a reaction page with it. All the pagination logic is taken care of but nothing more, the page index is returned and you have to send a callback to do something with it. | ||||||
|  */ |  */ | ||||||
|  | @ -251,44 +258,132 @@ export async function askMultipleChoice( | ||||||
|     if (!isDeleted) message.delete(); |     if (!isDeleted) message.delete(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** |  | ||||||
|  * Gets a user by their username. Gets the first one then rolls with it. |  | ||||||
|  */ |  | ||||||
| export async function getMemberByUsername(guild: Guild, username: string) { |  | ||||||
|     return ( |  | ||||||
|         await guild.members.fetch({ |  | ||||||
|             query: username, |  | ||||||
|             limit: 1 |  | ||||||
|         }) |  | ||||||
|     ).first(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Convenience function to handle cases where someone isn't found by a username automatically. |  | ||||||
|  */ |  | ||||||
| export async function callMemberByUsername( |  | ||||||
|     message: Message, |  | ||||||
|     username: string, |  | ||||||
|     onSuccess: (member: GuildMember) => void |  | ||||||
| ) { |  | ||||||
|     const guild = message.guild; |  | ||||||
|     const send = message.channel.send; |  | ||||||
| 
 |  | ||||||
|     if (guild) { |  | ||||||
|         const member = await getMemberByUsername(guild, username); |  | ||||||
| 
 |  | ||||||
|         if (member) onSuccess(member); |  | ||||||
|         else send(`Couldn't find a user by the name of \`${username}\`!`); |  | ||||||
|     } else send("You must execute this command in a server!"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // TO DO Section //
 |  | ||||||
| 
 |  | ||||||
| // getGuildByID() - checks for guild.available (boolean)
 |  | ||||||
| // getGuildByName()
 |  | ||||||
| // findMemberByNickname() - gets a member by their nickname or their username
 |  | ||||||
| // findUserByUsername()
 |  | ||||||
| 
 |  | ||||||
| // For "get x by y" methods:
 | // For "get x by y" methods:
 | ||||||
| // Caching: All guilds, channels, and roles are fully cached, while the caches for messages, users, and members aren't complete.
 | // Caching: All guilds, channels, and roles are fully cached, while the caches for messages, users, and members aren't complete.
 | ||||||
| // It's more reliable to get users/members by fetching their IDs. fetch() will searching through the cache anyway.
 | // It's more reliable to get users/members by fetching their IDs. fetch() will searching through the cache anyway.
 | ||||||
|  | // For guilds, do an extra check to make sure there isn't an outage (guild.available).
 | ||||||
|  | 
 | ||||||
|  | export function getGuildByID(id: string): Guild | SingleMessageOptions { | ||||||
|  |     const guild = client.guilds.cache.get(id); | ||||||
|  | 
 | ||||||
|  |     if (guild) { | ||||||
|  |         if (guild.available) return guild; | ||||||
|  |         else return {content: `The guild \`${guild.name}\` (ID: \`${id}\`) is unavailable due to an outage.`}; | ||||||
|  |     } else { | ||||||
|  |         return { | ||||||
|  |             content: `No guild found by the ID of \`${id}\`!` | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function getGuildByName(name: string): Guild | SingleMessageOptions { | ||||||
|  |     const query = name.toLowerCase(); | ||||||
|  |     const guild = client.guilds.cache.find((guild) => guild.name.toLowerCase().includes(query)); | ||||||
|  | 
 | ||||||
|  |     if (guild) { | ||||||
|  |         if (guild.available) return guild; | ||||||
|  |         else return {content: `The guild \`${guild.name}\` (ID: \`${guild.id}\`) is unavailable due to an outage.`}; | ||||||
|  |     } else { | ||||||
|  |         return { | ||||||
|  |             content: `No guild found by the name of \`${name}\`!` | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getChannelByID(id: string): Promise<Channel | SingleMessageOptions> { | ||||||
|  |     try { | ||||||
|  |         return await client.channels.fetch(id); | ||||||
|  |     } catch { | ||||||
|  |         return {content: `No channel found by the ID of \`${id}\`!`}; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Only go through the cached channels (non-DM channels). Plus, searching DM channels by name wouldn't really make sense, nor do they have names to search anyway.
 | ||||||
|  | export function getChannelByName(name: string): GuildChannel | SingleMessageOptions { | ||||||
|  |     const query = name.toLowerCase(); | ||||||
|  |     const channel = client.channels.cache.find( | ||||||
|  |         (channel) => channel instanceof GuildChannel && channel.name.toLowerCase().includes(query) | ||||||
|  |     ) as GuildChannel | undefined; | ||||||
|  |     if (channel) return channel; | ||||||
|  |     else return {content: `No channel found by the name of \`${name}\`!`}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getMessageByID( | ||||||
|  |     channel: TextChannel | DMChannel | NewsChannel | string, | ||||||
|  |     id: string | ||||||
|  | ): Promise<Message | SingleMessageOptions> { | ||||||
|  |     if (typeof channel === "string") { | ||||||
|  |         const targetChannel = await getChannelByID(channel); | ||||||
|  |         if (targetChannel instanceof TextChannel || targetChannel instanceof DMChannel) channel = targetChannel; | ||||||
|  |         else if (targetChannel instanceof Channel) return {content: `\`${id}\` isn't a valid text-based channel!`}; | ||||||
|  |         else return targetChannel; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |         return await channel.messages.fetch(id); | ||||||
|  |     } catch { | ||||||
|  |         return {content: `\`${id}\` isn't a valid message of the channel ${channel}!`}; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getUserByID(id: string): Promise<User | SingleMessageOptions> { | ||||||
|  |     try { | ||||||
|  |         return await client.users.fetch(id); | ||||||
|  |     } catch { | ||||||
|  |         return {content: `No user found by the ID of \`${id}\`!`}; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Also check tags (if provided) to narrow down users.
 | ||||||
|  | export function getUserByName(name: string): User | SingleMessageOptions { | ||||||
|  |     let query = name.toLowerCase(); | ||||||
|  |     const tagMatch = /^(.+?)#(\d{4})$/.exec(name); | ||||||
|  |     let tag: string | null = null; | ||||||
|  | 
 | ||||||
|  |     if (tagMatch) { | ||||||
|  |         query = tagMatch[1].toLowerCase(); | ||||||
|  |         tag = tagMatch[2]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const user = client.users.cache.find((user) => { | ||||||
|  |         const hasUsernameMatch = user.username.toLowerCase().includes(query); | ||||||
|  |         if (tag) return hasUsernameMatch && user.discriminator === tag; | ||||||
|  |         else return hasUsernameMatch; | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     if (user) return user; | ||||||
|  |     else return {content: `No user found by the name of \`${name}\`!`}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getMemberByID(guild: Guild, id: string): Promise<GuildMember | SingleMessageOptions> { | ||||||
|  |     try { | ||||||
|  |         return await guild.members.fetch(id); | ||||||
|  |     } catch { | ||||||
|  |         return {content: `No member found by the ID of \`${id}\`!`}; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // First checks if a member can be found by that nickname, then check if a member can be found by that username.
 | ||||||
|  | export async function getMemberByName(guild: Guild, name: string): Promise<GuildMember | SingleMessageOptions> { | ||||||
|  |     const member = ( | ||||||
|  |         await guild.members.fetch({ | ||||||
|  |             query: name, | ||||||
|  |             limit: 1 | ||||||
|  |         }) | ||||||
|  |     ).first(); | ||||||
|  | 
 | ||||||
|  |     // Search by username if no member is found, then resolve the user into a member if possible.
 | ||||||
|  |     if (member) { | ||||||
|  |         return member; | ||||||
|  |     } else { | ||||||
|  |         const user = getUserByName(name); | ||||||
|  | 
 | ||||||
|  |         if (user instanceof User) { | ||||||
|  |             const member = guild.members.resolve(user); | ||||||
|  |             if (member) return member; | ||||||
|  |             else return {content: `The user \`${user.tag}\` isn't in this guild!`}; | ||||||
|  |         } else { | ||||||
|  |             return {content: `No member found by the name of \`${name}\`!`}; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue