mirror of
				https://github.com/keanuplayz/TravBot-v3.git
				synced 2024-08-15 02:33:12 +00:00 
			
		
		
		
	Updated the documentation
This commit is contained in:
		
							parent
							
								
									5a64aed45d
								
							
						
					
					
						commit
						e7dfab7592
					
				
					 6 changed files with 82 additions and 75 deletions
				
			
		|  | @ -1,6 +1,12 @@ | ||||||
| # Table of Contents | # Table of Contents | ||||||
| 
 | 
 | ||||||
| ... | - [Structure](#structure) | ||||||
|  | - [Version Numbers](#version-numbers) | ||||||
|  | - [Message Subcommand Type](#message-subcommand-type) | ||||||
|  | - [Command Menu](#command-menu) | ||||||
|  | - [Command Metadata](#command-metadata) | ||||||
|  | - [Command Var String](#command-var-string) | ||||||
|  | - [Utility Functions](#utility-functions) | ||||||
| 
 | 
 | ||||||
| # Structure | # Structure | ||||||
| 
 | 
 | ||||||
|  | @ -36,96 +42,70 @@ Because versions are assigned to batches of changes rather than single changes ( | ||||||
| - `https://discord.com/channels/<id>/<id>/<id>` comes from the `Copy Message Link` button. | - `https://discord.com/channels/<id>/<id>/<id>` comes from the `Copy Message Link` button. | ||||||
| - `<id>-<id>` comes from holding `Shift` on the desktop application and clicking on the `Copy ID` button. | - `<id>-<id>` comes from holding `Shift` on the desktop application and clicking on the `Copy ID` button. | ||||||
| 
 | 
 | ||||||
|  | # Command Menu | ||||||
| 
 | 
 | ||||||
|  | - `args`: A list of arguments in the command. It's relative to the subcommand, so if you do `$test this 5`, `5` becomes `$.args[0]` if `this` is a subcommand. Args are already converted, so a `number` subcommand would return a number rather than a string. | ||||||
|  | - `client`: `message.client` | ||||||
|  | - `message`: `message` | ||||||
|  | - `channel`: `message.channel` | ||||||
|  | - `guild`: `message.guild` | ||||||
|  | - `author`: `message.author` | ||||||
|  | - `member`: `message.member` | ||||||
| 
 | 
 | ||||||
| # Cleanup is Soon™ | # Command Metadata | ||||||
| 
 | 
 | ||||||
| ## Convenience Functions | - `description`: The command description that'll appear in the help menu. | ||||||
|  | - `endpoint`: Whether or not any arguments are allowed after the command. | ||||||
|  | - `usage`: Defines a custom usage when showing the command in the help menu. | ||||||
|  | - `permission`: *(Inherits)* -1 (default) indicates to inherit, 0 is the lowest rank, 1 is second lowest rank, and so on. | ||||||
|  | - `nsfw`: *(Inherits)* Whether or not the command is restricted to NSFW channels and DM channels. | ||||||
|  | - `channelType`: *(Inherits)* Whether the command is restricted to guild channels, DM channels, or has no restriction. Uses the `CHANNEL_TYPE` enum provided by the command handler. | ||||||
| 
 | 
 | ||||||
| This modularizes certain patterns of code to make things easier. | # Command Var String | ||||||
| 
 | 
 | ||||||
| - `$.paginate()`: 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. | - `%author%` - A user mention of the person who called the command. | ||||||
|  | - `%prefix%` - The prefix of the current guild. | ||||||
| 
 | 
 | ||||||
| ```js | # Utility Functions | ||||||
|  | 
 | ||||||
|  | ## [src/core (libd)](../src/core/libd.ts) - Utility functions specific for working with Discord | ||||||
|  | 
 | ||||||
|  | `paginate()` | ||||||
|  | ```ts | ||||||
| const pages = ['one', 'two', 'three']; | const pages = ['one', 'two', 'three']; | ||||||
| const msg = await $.channel.send(pages[0]); | const msg = await channel.send(pages[0]); | ||||||
| 
 | 
 | ||||||
| $.paginate(msg, $.author.id, pages.length, (page) => { | paginate(msg, author.id, pages.length, (page) => { | ||||||
|   msg.edit(pages[page]); | 	msg.edit(pages[page]); | ||||||
| }); | }); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| - `$.prompt()`: Prompts the user about a decision before following through. | `prompt()` | ||||||
|  | ```ts | ||||||
|  | const msg = await channel.send('Are you sure you want to delete this?'); | ||||||
| 
 | 
 | ||||||
| ```js | prompt(msg, author.id, () => { | ||||||
| const msg = await $.channel.send('Are you sure you want to delete this?'); | 	//... | ||||||
| 
 |  | ||||||
| $.prompt(msg, $.author.id, () => { |  | ||||||
|   delete this; // Replace this with actual code. |  | ||||||
| }); | }); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| - `$.getMemberByUsername()`: Gets a user by their username. Gets the first one then rolls with it. | `callMemberByUsername()` | ||||||
| - `$.callMemberByUsername()`: Convenience function to handle cases where someone isn't found by a username automatically. | ```ts | ||||||
| 
 | callMemberByUsername(message, args.join(" "), (member) => { | ||||||
| ```js | 	channel.send(`Your nickname is ${member.nickname}.`); | ||||||
| $.callMemberByUsername($.message, $.args.join(' '), (member) => { |  | ||||||
|   $.channel.send(`Your nickname is ${member.nickname}.`); |  | ||||||
| }); | }); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## Dynamic Properties | ## [src/lib](../src/lib.ts) - General utility functions | ||||||
| 
 | 
 | ||||||
| These will be accessible only inside a `Command` and will change per message. |  | ||||||
| 
 |  | ||||||
| - `$.args`: A list of arguments in the command. It's relative to the subcommand, so if you do `$test this 5`, `5` becomes `$.args[0]` if `this` is a subcommand. Args are already converted, so a `number` subcommand would return a number rather than a string. |  | ||||||
| - `$.client`: `message.client` |  | ||||||
| - `$.message`: `message` |  | ||||||
| - `$.channel`: `message.channel` |  | ||||||
| - `$.guild`: `message.guild` |  | ||||||
| - `$.author`: `message.author` |  | ||||||
| - `$.member`: `message.member` |  | ||||||
| 
 |  | ||||||
| # Wrappers |  | ||||||
| 
 |  | ||||||
| This is similar to modifying a primitive object's `prototype` without actually doing so. |  | ||||||
| 
 |  | ||||||
| ## NumberWrapper |  | ||||||
| 
 |  | ||||||
| - `.pluralise()`: A substitute for not having to do `amount === 1 ? "singular" : "plural"`. For example, `$(x).pluralise("credit", "s")` will return `"1 credit"` and/or `"5 credits"` respectively. |  | ||||||
| - `.pluraliseSigned()`: This builds on `.pluralise()` and adds a sign at the beginning for marking changes/differences. `$(0).pluraliseSigned("credit", "s")` will return `"+0 credits"`. |  | ||||||
| 
 |  | ||||||
| ## StringWrapper |  | ||||||
| 
 |  | ||||||
| - `.replaceAll()`: A non-regex alternative to replacing everything in a string. `$("test").replaceAll('t', 'z')` = `"zesz"`. |  | ||||||
| - `.toTitleCase()`: Capitalizes the first letter of each word. `$("this is some text").toTitleCase()` = `"This Is Some Text"`. |  | ||||||
| 
 |  | ||||||
| ## ArrayWrapper |  | ||||||
| 
 |  | ||||||
| - `.random()`: Returns a random element from an array. `$([1,2,3]).random()` could be any one of those elements. |  | ||||||
| - `.split()`: Splits an array into different arrays by a specified length. `$([1,2,3,4,5,6,7,8,9,10]).split(3)` = `[[1,2,3],[4,5,6],[7,8,9],[10]]`. |  | ||||||
| 
 |  | ||||||
| # Other Library Functions |  | ||||||
| 
 |  | ||||||
| These do have to be manually imported, which are used more on a case-by-case basis. |  | ||||||
| 
 |  | ||||||
| - `formatTimestamp()`: Formats a `Date` object into your system's time. `YYYY-MM-DD HH:MM:SS` |  | ||||||
| - `formatUTCTimestamp()`: Formats a `Date` object into UTC time. `YYYY-MM-DD HH:MM:SS` |  | ||||||
| - `botHasPermission()`: Tests if a bot has a certain permission in a specified guild. |  | ||||||
| - `parseArgs()`: Turns `call test "args with spaces" "even more spaces"` into `["call", "test", "args with spaces", "even more spaces"]`, inspired by the command line. | - `parseArgs()`: Turns `call test "args with spaces" "even more spaces"` into `["call", "test", "args with spaces", "even more spaces"]`, inspired by the command line. | ||||||
| - `parseVars()`: Replaces all `%` args in a string with stuff you specify. For example, you can replace all `nop` with `asm`, and `register %nop%` will turn into `register asm`. Useful for storing strings with variables in one place them accessing them in another place. | - `parseVars()`: Replaces all `%` args in a string with stuff you specify. For example, you can replace all `nop` with `asm`, and `register %nop%` will turn into `register asm`. Useful for storing strings with variables in one place them accessing them in another place. | ||||||
| - `isType()`: Used for type-checking. Useful for testing `any` types. | - `isType()`: Used for type-checking. Useful for testing `any` types. | ||||||
| - `select()`: Checks if a variable matches a certain type and uses the fallback value if not. (Warning: Type checking is based on the fallback's type. Be sure that the "type" parameter is accurate to this!) | - `select()`: Checks if a variable matches a certain type and uses the fallback value if not. (Warning: Type checking is based on the fallback's type. Be sure that the "type" parameter is accurate to this!) | ||||||
| - `Random`: An object of functions containing stuff related to randomness. `Random.num` is a random decimal, `Random.int` is a random integer, `Random.chance` takes a number ranging from `0` to `1` as a percentage. `Random.sign` takes a number and has a 50-50 chance to be negative or positive. `Random.deviation` takes a number and a magnitude and produces a random number within those confines. `(5, 2)` would produce any number between `3` and `7`. | - `Random`: An object of functions containing stuff related to randomness. `Random.num` is a random decimal, `Random.int` is a random integer, `Random.chance` takes a number ranging from `0` to `1` as a percentage. `Random.sign` takes a number and has a 50-50 chance to be negative or positive. `Random.deviation` takes a number and a magnitude and produces a random number within those confines. `(5, 2)` would produce any number between `3` and `7`. | ||||||
| 
 | - `pluralise()`: A substitute for not having to do `amount === 1 ? "singular" : "plural"`. For example, `pluralise(x, "credit", "s")` will return `"1 credit"` and/or `"5 credits"` respectively. | ||||||
| # Other Core Functions | - `pluraliseSigned()`: This builds on `pluralise()` and adds a sign at the beginning for marking changes/differences. `pluraliseSigned(0, "credit", "s")` will return `"+0 credits"`. | ||||||
| 
 | - `replaceAll()`: A non-regex alternative to replacing everything in a string. `replaceAll("test", "t", "z")` = `"zesz"`. | ||||||
| - `permissions::hasPermission()`: Checks if a `Member` has a certain permission. | - `toTitleCase()`: Capitalizes the first letter of each word. `toTitleCase("this is some text")` = `"This Is Some Text"`. | ||||||
| - `permissions::getPermissionLevel()`: Gets a `Member`'s permission level according to the permissions enum defined in the file. | - `random()`: Returns a random element from an array. `random([1,2,3])` could be any one of those elements. | ||||||
| - `structures::getPrefix()`: Get the current prefix of the guild or the bot's prefix if none is found. | - `split()`: Splits an array into different arrays by a specified length. `split([1,2,3,4,5,6,7,8,9,10], 3)` = `[[1,2,3],[4,5,6],[7,8,9],[10]]`. | ||||||
| 
 |  | ||||||
| # The other core files |  | ||||||
| 
 |  | ||||||
| - `core/permissions`: Contains all the permission roles and checking functions. |  | ||||||
| - `core/structures`: Contains all the code handling dynamic JSON data. Has a one-to-one connection with each file generated, for example, `Config` which calls `super("config")` meaning it writes to `data/config.json`. |  | ||||||
| - `core/storage`: Handles most of the file system operations, all of the ones related to `data` at least. |  | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ export default new NamedCommand({ | ||||||
| 
 | 
 | ||||||
| ### Quick note on the run property | ### Quick note on the run property | ||||||
| 
 | 
 | ||||||
| You can also enter a string for the `run` property which will send a message with that string specified ([you can also specify some variables in that string](Documentation.md#)). The above is functionally equivalent to the below. | You can also enter a string for the `run` property which will send a message with that string specified ([you can also specify some variables in that string](Documentation.md#command-var-string)). The above is functionally equivalent to the below. | ||||||
| 
 | 
 | ||||||
| ```ts | ```ts | ||||||
| import {Command, NamedCommand} from "../core"; | import {Command, NamedCommand} from "../core"; | ||||||
|  | @ -70,7 +70,7 @@ export default new NamedCommand({ | ||||||
| }); | }); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Here, . For example, if this file was named `test.ts`, `$test <@237359961842253835>` would get the user by the ID `237359961842253835` into `args[0]` as a [User](https://discord.js.org/#/docs/main/stable/class/User) object. `$test experiment` would run as if you just called `$test` *(given that [endpoint](Documentation.md#) isn't set to `true`)*. | Here, . For example, if this file was named `test.ts`, `$test <@237359961842253835>` would get the user by the ID `237359961842253835` into `args[0]` as a [User](https://discord.js.org/#/docs/main/stable/class/User) object. `$test experiment` would run as if you just called `$test` *(given that [endpoint](Documentation.md#command-metadata) isn't set to `true`)*. | ||||||
| 
 | 
 | ||||||
| If you want, you can typecast the argument to be more strongly typed, because the type of `args` is `any[]`. *([See why if you're curious.](DesignDecisions.md#any[]-parameters-for-subcommand-run))* | If you want, you can typecast the argument to be more strongly typed, because the type of `args` is `any[]`. *([See why if you're curious.](DesignDecisions.md#any[]-parameters-for-subcommand-run))* | ||||||
| 
 | 
 | ||||||
|  | @ -171,7 +171,7 @@ export default new NamedCommand({ | ||||||
| 
 | 
 | ||||||
| Here, the property `channelType` would spread to all subcommands unless a subcommand defines it. Using the above example, the `channelType` for both `$siege` and `$siege pineapple` would be `CHANNEL_TYPE.GUILD`. | Here, the property `channelType` would spread to all subcommands unless a subcommand defines it. Using the above example, the `channelType` for both `$siege` and `$siege pineapple` would be `CHANNEL_TYPE.GUILD`. | ||||||
| 
 | 
 | ||||||
| *To get a full list of metadata properties, see the [documentation](Documentation.md#).* | *To get a full list of metadata properties, see the [documentation](Documentation.md#command-menu).* | ||||||
| 
 | 
 | ||||||
| ## Utility Functions | ## Utility Functions | ||||||
| 
 | 
 | ||||||
|  | @ -187,7 +187,7 @@ export default new NamedCommand({ | ||||||
| }); | }); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| *To get a full list of utility functions, see the [documentation](Documentation.md#).* | *To get a full list of utility functions, see the [documentation](Documentation.md#utility-functions).* | ||||||
| 
 | 
 | ||||||
| # Adding a new non-command feature | # Adding a new non-command feature | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,6 +13,9 @@ import {unreactEventListeners, replyEventListeners} from "./eventListeners"; | ||||||
| 
 | 
 | ||||||
| export type SingleMessageOptions = MessageOptions & {split?: false}; | export type SingleMessageOptions = MessageOptions & {split?: false}; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Tests if a bot has a certain permission in a specified guild. | ||||||
|  |  */ | ||||||
| export function botHasPermission(guild: Guild | null, permission: number): boolean { | export function botHasPermission(guild: Guild | null, permission: number): boolean { | ||||||
|     return !!guild?.me?.hasPermission(permission); |     return !!guild?.me?.hasPermission(permission); | ||||||
| } | } | ||||||
|  | @ -21,6 +24,10 @@ export function botHasPermission(guild: Guild | null, permission: number): boole | ||||||
| 
 | 
 | ||||||
| // Pagination function that allows for customization via a callback.
 | // 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.
 | // 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. | ||||||
|  |  */ | ||||||
| export async function paginate( | export async function paginate( | ||||||
|     channel: TextChannel | DMChannel | NewsChannel, |     channel: TextChannel | DMChannel | NewsChannel, | ||||||
|     senderID: string, |     senderID: string, | ||||||
|  | @ -90,6 +97,9 @@ export async function paginate( | ||||||
| // Waits for the sender to either confirm an action or let it pass (and delete the message).
 | // Waits for the sender to either confirm an action or let it pass (and delete the message).
 | ||||||
| // This should probably be renamed to "confirm" now that I think of it, "prompt" is better used elsewhere.
 | // This should probably be renamed to "confirm" now that I think of it, "prompt" is better used elsewhere.
 | ||||||
| // Append "\n*(This message will automatically be deleted after 10 seconds.)*" in the future?
 | // Append "\n*(This message will automatically be deleted after 10 seconds.)*" in the future?
 | ||||||
|  | /** | ||||||
|  |  * Prompts the user about a decision before following through. | ||||||
|  |  */ | ||||||
| export async function prompt(message: Message, senderID: string, onConfirm: () => void, duration = 10000) { | export async function prompt(message: Message, senderID: string, onConfirm: () => void, duration = 10000) { | ||||||
|     let isDeleted = false; |     let isDeleted = false; | ||||||
| 
 | 
 | ||||||
|  | @ -222,6 +232,9 @@ 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) { | export async function getMemberByUsername(guild: Guild, username: string) { | ||||||
|     return ( |     return ( | ||||||
|         await guild.members.fetch({ |         await guild.members.fetch({ | ||||||
|  | @ -231,7 +244,9 @@ export async function getMemberByUsername(guild: Guild, username: string) { | ||||||
|     ).first(); |     ).first(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** Convenience function to handle false cases automatically. */ | /** | ||||||
|  |  * Convenience function to handle cases where someone isn't found by a username automatically. | ||||||
|  |  */ | ||||||
| export async function callMemberByUsername( | export async function callMemberByUsername( | ||||||
|     message: Message, |     message: Message, | ||||||
|     username: string, |     username: string, | ||||||
|  |  | ||||||
|  | @ -1,12 +1,19 @@ | ||||||
|  | // Contains all the permission roles and checking functions.
 | ||||||
| import {User, GuildMember} from "discord.js"; | import {User, GuildMember} from "discord.js"; | ||||||
| import {permissionLevels} from "./interface"; | import {permissionLevels} from "./interface"; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Checks if a `Member` has a certain permission. | ||||||
|  |  */ | ||||||
| export function hasPermission(user: User, member: GuildMember | null, permission: number): boolean { | export function hasPermission(user: User, member: GuildMember | null, permission: number): boolean { | ||||||
|     for (let i = permissionLevels.length - 1; i >= permission; i--) |     for (let i = permissionLevels.length - 1; i >= permission; i--) | ||||||
|         if (permissionLevels[i].check(user, member)) return true; |         if (permissionLevels[i].check(user, member)) return true; | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Gets a `Member`'s permission level according to the permissions enum defined in the file. | ||||||
|  |  */ | ||||||
| export function getPermissionLevel(user: User, member: GuildMember | null): number { | export function getPermissionLevel(user: User, member: GuildMember | null): number { | ||||||
|     for (let i = permissionLevels.length - 1; i >= 0; i--) if (permissionLevels[i].check(user, member)) return i; |     for (let i = permissionLevels.length - 1; i >= 0; i--) if (permissionLevels[i].check(user, member)) return i; | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | // Handles most of the file system operations, all of the ones related to `data` at least.
 | ||||||
| import fs from "fs"; | import fs from "fs"; | ||||||
| 
 | 
 | ||||||
| const Storage = { | const Storage = { | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | // Contains all the code handling dynamic JSON data. Has a one-to-one connection with each file generated, for example, `Config` which calls `super("config")` meaning it writes to `data/config.json`.
 | ||||||
| import FileManager from "./modules/storage"; | import FileManager from "./modules/storage"; | ||||||
| import {select, GenericJSON, GenericStructure} from "./lib"; | import {select, GenericJSON, GenericStructure} from "./lib"; | ||||||
| import {watch} from "fs"; | import {watch} from "fs"; | ||||||
|  | @ -145,6 +146,9 @@ if (IS_DEV_MODE) { | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Get the current prefix of the guild or the bot's prefix if none is found. | ||||||
|  |  */ | ||||||
| export function getPrefix(guild: DiscordGuild | null): string { | export function getPrefix(guild: DiscordGuild | null): string { | ||||||
|     let prefix = Config.prefix; |     let prefix = Config.prefix; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue