refactor: run prettier

This commit is contained in:
Anthony Berg 2023-11-18 22:01:33 +00:00
parent 1a8b6eb0c1
commit 5d93db6365
126 changed files with 2392 additions and 1499 deletions

View File

@ -1,39 +1,29 @@
{ {
"env": { "env": {
"browser": true, "browser": true,
"es2021": true "es2021": true
},
"extends": ["airbnb-base", "airbnb-typescript/base", "prettier"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"project": "tsconfig.json"
},
"plugins": ["@typescript-eslint", "import"],
"rules": {
"import/no-unresolved": "error",
"import/prefer-default-export": "off",
"class-methods-use-this": "off"
},
"settings": {
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"]
}, },
"extends": [ "import/resolver": {
"airbnb-base", "typescript": {
"airbnb-typescript/base", "alwaysTryTypes": true
"prettier" }
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"project": "tsconfig.json"
},
"plugins": [
"@typescript-eslint",
"import"
],
"rules": {
"import/no-unresolved": "error",
"import/prefer-default-export": "off",
"class-methods-use-this": "off"
},
"settings": {
"import/parsers": {
"@typescript-eslint/parser": [
".ts",
".tsx"
]
},
"import/resolver": {
"typescript": {
"alwaysTryTypes": true
}
}
} }
}
} }

View File

@ -4,7 +4,6 @@ about: Create a report to help us improve
title: '' title: ''
labels: bug labels: bug
assignees: '' assignees: ''
--- ---
**Describe the bug** **Describe the bug**
@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
**To Reproduce** **To Reproduce**
Steps to reproduce the behavior: Steps to reproduce the behavior:
1. Go to '...' 1. Go to '...'
2. Click on '....' 2. Click on '....'
3. Scroll down to '....' 3. Scroll down to '....'
@ -24,15 +24,17 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem. If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):** **Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari] - OS: [e.g. iOS]
- Version [e.g. 22] - Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):** **Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1] - Device: [e.g. iPhone6]
- Browser [e.g. stock browser, safari] - OS: [e.g. iOS8.1]
- Version [e.g. 22] - Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.

View File

@ -4,7 +4,6 @@ about: Suggest an idea for this project
title: '' title: ''
labels: enhancement labels: enhancement
assignees: '' assignees: ''
--- ---
**Is your feature request related to a problem? Please describe.** **Is your feature request related to a problem? Please describe.**

View File

@ -1,7 +1,5 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": ["config:base"],
"config:base"
],
"schedule": ["after 12pm and before 6pm on Saturday"] "schedule": ["after 12pm and before 6pm on Saturday"]
} }

View File

@ -9,14 +9,14 @@
# the `language` matrix defined below to confirm you have the correct set of # the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages. # supported CodeQL languages.
# #
name: "CodeQL" name: 'CodeQL'
on: on:
push: push:
branches: [ "main" ] branches: ['main']
pull_request: pull_request:
# The branches below must be a subset of the branches above # The branches below must be a subset of the branches above
branches: [ "main" ] branches: ['main']
schedule: schedule:
- cron: '37 11 * * 2' - cron: '37 11 * * 2'
@ -32,41 +32,40 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: [ 'javascript' ] language: ['javascript']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file. # By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file. # Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # queries: security-extended,security-and-quality
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell. # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# If the Autobuild fails above, remove it and uncomment the following three lines. # Command-line programs to run using the OS shell.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# - run: | # If the Autobuild fails above, remove it and uncomment the following three lines.
# echo "Run, Build Application using script" # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis # - run: |
uses: github/codeql-action/analyze@v2 # echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@ -11,10 +11,10 @@ name: ESLint
on: on:
push: push:
branches: [ "main" ] branches: ['main']
pull_request: pull_request:
# The branches below must be a subset of the branches above # The branches below must be a subset of the branches above
branches: [ "main" ] branches: ['main']
schedule: schedule:
- cron: '27 13 * * 1' - cron: '27 13 * * 1'
@ -38,7 +38,7 @@ jobs:
run: npx eslint . run: npx eslint .
--config .eslintrc.json --config .eslintrc.json
--ext .js,.jsx,.ts,.tsx --ext .js,.jsx,.ts,.tsx
--format @microsoft/eslint-formatter-sarif --format @microsoft/eslint-formatter-sarif
--output-file eslint-results.sarif --output-file eslint-results.sarif
continue-on-error: true continue-on-error: true

View File

@ -2,10 +2,10 @@ name: Prettier
on: on:
push: push:
branches: [ "main" ] branches: ['main']
pull_request: pull_request:
# The branches below must be a subset of the branches above # The branches below must be a subset of the branches above
branches: [ "main" ] branches: ['main']
schedule: schedule:
- cron: '27 13 * * 1' - cron: '27 13 * * 1'

View File

@ -14,7 +14,6 @@ Make sure to create the .env file, which you can use the [.env.example](.env.exa
There are 2 options for running this bot, one using docker-compose and the other, less desirable npm. There are 2 options for running this bot, one using docker-compose and the other, less desirable npm.
### Docker ### Docker
Running the bot Dockerised makes everything easier. To run the bot, run: Running the bot Dockerised makes everything easier. To run the bot, run:
@ -28,11 +27,13 @@ docker-compose up -d
Make sure to run `npm install` if you just cloned the repo. Make sure to run `npm install` if you just cloned the repo.
Then make sure to compile the TypeScript files using Then make sure to compile the TypeScript files using
```shell ```shell
npm run build npm run build
``` ```
If you are running the code for the first time with a new database, make sure to run `npm run start:migrate`, otherwise run: If you are running the code for the first time with a new database, make sure to run `npm run start:migrate`, otherwise run:
```shell ```shell
npm start npm start
``` ```
@ -66,4 +67,4 @@ For support, feel free to send an email to anthony@aramovement.org or reach out
This bot is free and open source. It licensed using [GPL v3](LICENSE). This bot is free and open source. It licensed using [GPL v3](LICENSE).
Well done on making it to the bottom of the README file :) Well done on making it to the bottom of the README file :)

View File

@ -1,4 +1,4 @@
version: "3.7" version: '3.7'
services: services:
postgres: postgres:
image: postgres:15 image: postgres:15
@ -43,4 +43,4 @@ volumes:
name: arabot-redis name: arabot-redis
networks: networks:
arabot: arabot:

View File

@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our Examples of behavior that contributes to a positive environment for our
community include: community include:
* Demonstrating empathy and kindness toward other people - Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences - Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback - Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes, - Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience and learning from the experience
* Focusing on what is best not just for us as individuals, but for the - Focusing on what is best not just for us as individuals, but for the
overall community overall community
Examples of unacceptable behavior include: Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or - The use of sexualized language or imagery, and sexual attention or
advances of any kind advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks - Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment - Public or private harassment
* Publishing others' private information, such as a physical or email - Publishing others' private information, such as a physical or email
address, without their explicit permission address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a - Other conduct which could reasonably be considered inappropriate in a
professional setting professional setting
## Enforcement Responsibilities ## Enforcement Responsibilities
@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban ### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community **Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals. individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within **Consequence**: A permanent ban from any sort of public interaction within

View File

@ -1,11 +1,12 @@
# Commands for the bot # Commands for the bot
These are all the commands that you can use for the bot. Some of these are for staff only, but everyone can use the These are all the commands that you can use for the bot. Some of these are for staff only, but everyone can use the
general commands general commands
## Contents ## Contents
- [General](commands/GENERAL.md) - [General](commands/GENERAL.md)
- [Moderator](commands/MOD.md) - [Moderator](commands/MOD.md)
- [Verifier](commands/VERIFIER.md) - [Verifier](commands/VERIFIER.md)
- [Mentor](commands/MENTOR.md) - [Mentor](commands/MENTOR.md)
- [Coordinator](commands/COORDINATOR.md) - [Coordinator](commands/COORDINATOR.md)

View File

@ -1,13 +1,12 @@
# Commit Message Format # Commit Message Format
*This specification is a modified version of the [AngularJS commit message format](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-format).* _This specification is a modified version of the [AngularJS commit message format](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-format)._
We have very precise rules over how our Git commit messages must be formatted. We have very precise rules over how our Git commit messages must be formatted.
This format leads to **easier to read commit history**. This format leads to **easier to read commit history**.
Each commit message consists of a **header**, a **body**, and a **footer**. Each commit message consists of a **header**, a **body**, and a **footer**.
``` ```
<header> <header>
<BLANK LINE> <BLANK LINE>
@ -23,7 +22,6 @@ When the body is present it must be at least 20 characters long and must conform
The `footer` is optional. The [Commit Message Footer](#commit-footer) format describes what the footer is used for and the structure it must have. The `footer` is optional. The [Commit Message Footer](#commit-footer) format describes what the footer is used for and the structure it must have.
#### <a name="commit-header"></a>Commit Message Header #### <a name="commit-header"></a>Commit Message Header
``` ```
@ -38,42 +36,39 @@ The `footer` is optional. The [Commit Message Footer](#commit-footer) format des
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional. The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
##### Type ##### Type
Must be one of the following: Must be one of the following:
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) - **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
* **ci**: Changes to our CI configuration files and scripts - **ci**: Changes to our CI configuration files and scripts
* **docs**: Documentation only changes - **docs**: Documentation only changes
* **feat**: A new feature - **feat**: A new feature
* **fix**: A bug fix - **fix**: A bug fix
* **perf**: A code change that improves performance - **perf**: A code change that improves performance
* **refactor**: A code change that neither fixes a bug nor adds a feature - **refactor**: A code change that neither fixes a bug nor adds a feature
* **test**: Adding missing tests or correcting existing tests - **test**: Adding missing tests or correcting existing tests
##### Scope ##### Scope
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages). The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
The following is the list of supported scopes: The following is the list of supported scopes:
* `arabot` - `arabot`
* `config` - `config`
* `compiler` - `compiler`
* `database` - `database`
* `docs` - `docs`
* `upgrade` - `upgrade`
##### Summary ##### Summary
Use the summary field to provide a succinct description of the change: Use the summary field to provide a succinct description of the change:
* use the imperative, present tense: "change" not "changed" nor "changes" - use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize the first letter - don't capitalize the first letter
* no dot (.) at the end - no dot (.) at the end
#### <a name="commit-body"></a>Commit Message Body #### <a name="commit-body"></a>Commit Message Body
@ -82,7 +77,6 @@ Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change. Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change. You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
#### <a name="commit-footer"></a>Commit Message Footer #### <a name="commit-footer"></a>Commit Message Footer
The footer can contain information about breaking changes and deprecations and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to. The footer can contain information about breaking changes and deprecations and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
@ -112,7 +106,6 @@ Breaking Change section should start with the phrase "BREAKING CHANGE: " followe
Similarly, a Deprecation section should start with "DEPRECATED: " followed by a short description of what is deprecated, a blank line, and a detailed description of the deprecation that also mentions the recommended update path. Similarly, a Deprecation section should start with "DEPRECATED: " followed by a short description of what is deprecated, a blank line, and a detailed description of the deprecation that also mentions the recommended update path.
### Revert commits ### Revert commits
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.

View File

@ -5,8 +5,8 @@
- `/ping`/`?ping` - Checks if the bot is alive and the ping of the bot. - `/ping`/`?ping` - Checks if the bot is alive and the ping of the bot.
- `/apply`/`?apply` - Gives you the link to where you can apply to be a Moderator or Verifier. - `/apply`/`?apply` - Gives you the link to where you can apply to be a Moderator or Verifier.
- `/count`/`?count` - Tells you how many vegans and non-vegans there are on the server. - `/count`/`?count` - Tells you how many vegans and non-vegans there are on the server.
- `/info <info> <optional: visible>` - Gives you information based on what you pick in `<info>`. If you make `visible` - `/info <info> <optional: visible>` - Gives you information based on what you pick in `<info>`. If you make `visible`
true, it will make the information visible to everyone. true, it will make the information visible to everyone.
- `/help`/`?help` - Gives a link (here) to all the commands. - `/help`/`?help` - Gives a link (here) to all the commands.
## Economy ## Economy
@ -18,7 +18,7 @@ true, it will make the information visible to everyone.
## XP ## XP
- `/rank <optional: user>`/`?rank <optional: user>` - Shows your rank based on the amount of XP you have. If you provide - `/rank <optional: user>`/`?rank <optional: user>` - Shows your rank based on the amount of XP you have. If you provide
a user, it will display that user's rank instead. a user, it will display that user's rank instead.
## Fun Commands ## Fun Commands
@ -29,4 +29,4 @@ a user, it will display that user's rank instead.
- `/poke` - `/poke`
- `/sad` - `/sad`
- `/shrug` - `/shrug`
- `/cringe` - `/cringe`

View File

@ -4,12 +4,12 @@
- `/rename <user> <optional: nickname>`/`?ru <user> <optional: nickname>` - Renames that user to the specified nickname, - `/rename <user> <optional: nickname>`/`?ru <user> <optional: nickname>` - Renames that user to the specified nickname,
if nickname is left blank it will reset the nickname to their original username. if nickname is left blank it will reset the nickname to their original username.
- `/slowmode <duration>`/`?slowmode <duration>` - changes the slowmode for a chat. Duration uses a time which can be set by providing a number - `/slowmode <duration>`/`?slowmode <duration>` - changes the slowmode for a chat. Duration uses a time which can be set by providing a number
followed by s/d/m/y or just writing `off`. These can be combined. followed by s/d/m/y or just writing `off`. These can be combined.
For example to set the slowmode for 1 minute and 30 seconds, you would write: `1m 30s`. For example to set the slowmode for 1 minute and 30 seconds, you would write: `1m 30s`.
- `/softmute <user>`/`?sm/softmute <user>` - Prevents the user from reacting to messages. - `/softmute <user>`/`?sm/softmute <user>` - Prevents the user from reacting to messages.
- `/vcmute <user>`/`?vcmute <user>` - Adds a persistent VC mute if the user has left the VC or leaves the server to - `/vcmute <user>`/`?vcmute <user>` - Adds a persistent VC mute if the user has left the VC or leaves the server to
circumvent VC mutes. circumvent VC mutes.
- `?warn <user> <reason>` - Gives a warning to the user. - `?warn <user> <reason>` - Gives a warning to the user.
## Roles ## Roles
@ -36,15 +36,15 @@ These are used for users that have broken rules severe enough that takes away th
- `/restrict <user> <reason>`/`?r/restrict <user> <reason>` - Restricts the user to the restricted section - `/restrict <user> <reason>`/`?r/restrict <user> <reason>` - Restricts the user to the restricted section
- `/unrestrict <user>`/`?ur <user>` - Unrestricts the user - `/unrestrict <user>`/`?ur <user>` - Unrestricts the user
- `/restrictlogs <optional: user>` - Shows the logs of when the user has been restricted. The need to provide the user - `/restrictlogs <optional: user>` - Shows the logs of when the user has been restricted. The need to provide the user
is optional depending on if the command is run in the ModMail category. is optional depending on if the command is run in the ModMail category.
- `/restricttools channel delete <optional: user>` - Deletes the vegan restricted channel for the user. Providing a user - `/restricttools channel delete <optional: user>` - Deletes the vegan restricted channel for the user. Providing a user
is only optional if the command is run in the channel that is to be deleted. is only optional if the command is run in the channel that is to be deleted.
## Bans ## Bans
- `/tempban <user> <duration> <reason>`/`?tempban <user> <duration <reason>` - Bans the user for a specific amount of - `/tempban <user> <duration> <reason>`/`?tempban <user> <duration <reason>` - Bans the user for a specific amount of
time. Duration uses a time which can be set by providing a number followed by s/d/m/y. These can be combined. time. Duration uses a time which can be set by providing a number followed by s/d/m/y. These can be combined.
For example to ban someone for 1 week and 3 days, you would write: `1w 3d`. For example to ban someone for 1 week and 3 days, you would write: `1w 3d`.
- `/ban <user> <reason>`/`?ban <user> <reason>` - Permanently bans that user. - `/ban <user> <reason>`/`?ban <user> <reason>` - Permanently bans that user.
- `/unban <user>`/`?unban <user>` - Unbans that user. - `/unban <user>`/`?unban <user>` - Unbans that user.

View File

@ -2,9 +2,10 @@
## Verification ## Verification
- `/verify <user> <roles>`/`?ver <user> <roles>` - This is a manual verification to give roles to a user. This should - `/verify <user> <roles>`/`?ver <user> <roles>` - This is a manual verification to give roles to a user. This should
not be used if you are verifying the user in the voice channel. Roles available (you can write multiple in one command not be used if you are verifying the user in the voice channel. Roles available (you can write multiple in one command
such as `v a t`): such as `v a t`):
- `v` - Vegan - `v` - Vegan
- `a` - Activist - `a` - Activist
- `t` - Trusted - `t` - Trusted
@ -13,8 +14,8 @@ such as `v a t`):
- `conv` - Convinced - `conv` - Convinced
- `veg` - Veg Curious - `veg` - Veg Curious
- `/verifytimeoutremove <user>` - Removes a verification timeout if the user has been timed out as a verifier was not - `/verifytimeoutremove <user>` - Removes a verification timeout if the user has been timed out as a verifier was not
available. This cannot be used for users that have been verified. available. This cannot be used for users that have been verified.
## Roles ## Roles

View File

@ -26,7 +26,8 @@ export class AccessCommand extends Command {
super(context, { super(context, {
...options, ...options,
name: 'access', name: 'access',
description: 'Manages channel permissions for ModMails, Private channels, and restricted channels', description:
'Manages channel permissions for ModMails, Private channels, and restricted channels',
preconditions: ['CoordinatorOnly'], preconditions: ['CoordinatorOnly'],
}); });
} }
@ -34,25 +35,38 @@ export class AccessCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addStringOption((option) => option.setName('permission') .setDescription(this.description)
.setDescription('Select permissions for the user/role') .addStringOption((option) =>
.setRequired(true) option
.addChoices( .setName('permission')
{ name: 'Add', value: 'add' }, .setDescription('Select permissions for the user/role')
{ name: 'Read', value: 'read' }, .setRequired(true)
{ name: 'Remove', value: 'remove' }, .addChoices(
{ name: 'Reset', value: 'reset' }, { name: 'Add', value: 'add' },
)) { name: 'Read', value: 'read' },
.addChannelOption((option) => option.setName('channel') { name: 'Remove', value: 'remove' },
.setDescription('Channel to change these permissions on') { name: 'Reset', value: 'reset' },
.setRequired(true)) ),
.addUserOption((option) => option.setName('user') )
.setDescription('User to set these permissions for')) .addChannelOption((option) =>
.addRoleOption((option) => option.setName('role') option
.setDescription('Role to set these permissions for')), .setName('channel')
.setDescription('Channel to change these permissions on')
.setRequired(true),
)
.addUserOption((option) =>
option
.setName('user')
.setDescription('User to set these permissions for'),
)
.addRoleOption((option) =>
option
.setName('role')
.setDescription('Role to set these permissions for'),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -88,15 +102,18 @@ export class AccessCommand extends Command {
// If user and role is provided, the return an error // If user and role is provided, the return an error
if (user !== null && role !== null) { if (user !== null && role !== null) {
await interaction.reply({ await interaction.reply({
content: 'You have entered a user and a role at the same time! Please only enter one at a time.', content:
'You have entered a user and a role at the same time! Please only enter one at a time.',
ephemeral: true, ephemeral: true,
}); });
return; return;
} }
// Checks that the channel is a GuildText or GuildVoice, otherwise, return error // Checks that the channel is a GuildText or GuildVoice, otherwise, return error
if (channel.type !== ChannelType.GuildText if (
&& channel.type !== ChannelType.GuildVoice) { channel.type !== ChannelType.GuildText &&
channel.type !== ChannelType.GuildVoice
) {
await interaction.reply({ await interaction.reply({
content: 'Please only select a text or voice channel!', content: 'Please only select a text or voice channel!',
ephemeral: true, ephemeral: true,
@ -105,9 +122,11 @@ export class AccessCommand extends Command {
} }
// If the channel is not in the categories ModMail, Private, Restricted, the return error // If the channel is not in the categories ModMail, Private, Restricted, the return error
if (channel.parentId !== IDs.categories.modMail if (
&& channel.parentId !== IDs.categories.private channel.parentId !== IDs.categories.modMail &&
&& channel.parentId !== IDs.categories.restricted) { channel.parentId !== IDs.categories.private &&
channel.parentId !== IDs.categories.restricted
) {
await interaction.reply({ await interaction.reply({
content: 'Channel is not in ModMail/Private/Restricted category!', content: 'Channel is not in ModMail/Private/Restricted category!',
ephemeral: true, ephemeral: true,

View File

@ -35,14 +35,21 @@ export class AnonymousCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addStringOption((option) => option.setName('message') .setDescription(this.description)
.setDescription('The message the bot will send') .addStringOption((option) =>
.setRequired(true)) option
.addChannelOption((option) => option.setName('channel') .setName('message')
.setDescription('The channel the bot will send the message')), .setDescription('The message the bot will send')
.setRequired(true),
)
.addChannelOption((option) =>
option
.setName('channel')
.setDescription('The channel the bot will send the message'),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },

View File

@ -33,14 +33,18 @@ export class ClearCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addIntegerOption((option) => option.setName('messages') .setDescription(this.description)
.setDescription('Number of messages to clear') .addIntegerOption((option) =>
.setRequired(true) option
.setMinValue(1) .setName('messages')
.setMaxValue(100)), .setDescription('Number of messages to clear')
.setRequired(true)
.setMinValue(1)
.setMaxValue(100),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -53,8 +57,7 @@ export class ClearCommand extends Command {
const messages = interaction.options.getInteger('messages', true); const messages = interaction.options.getInteger('messages', true);
const { channel } = interaction; const { channel } = interaction;
if (channel === null if (channel === null || channel.isDMBased()) {
|| channel.isDMBased()) {
await interaction.reply({ await interaction.reply({
content: 'Could not fetch channel!', content: 'Could not fetch channel!',
ephemeral: true, ephemeral: true,
@ -89,8 +92,7 @@ export class ClearCommand extends Command {
const { channel } = message; const { channel } = message;
if (!channel.isTextBased() if (!channel.isTextBased() || channel.isDMBased()) {
|| channel.isDMBased()) {
await message.react('❌'); await message.react('❌');
await message.reply('Unsupported channel type!'); await message.reply('Unsupported channel type!');
return; return;

View File

@ -53,18 +53,31 @@ export class PrivateCommand extends Subcommand {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Subcommand.Registry) { public override registerApplicationCommands(registry: Subcommand.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addSubcommand((command) => command.setName('create') .setDescription(this.description)
.setDescription('Create a private channel') .addSubcommand((command) =>
.addUserOption((option) => option.setName('user') command
.setDescription('User to create a private channel with') .setName('create')
.setRequired(true))) .setDescription('Create a private channel')
.addSubcommand((command) => command.setName('delete') .addUserOption((option) =>
.setDescription('Delete a private channel') option
.addUserOption((option) => option.setName('user') .setName('user')
.setDescription('User to delete a private channel from'))), .setDescription('User to create a private channel with')
.setRequired(true),
),
)
.addSubcommand((command) =>
command
.setName('delete')
.setDescription('Delete a private channel')
.addUserOption((option) =>
option
.setName('user')
.setDescription('User to delete a private channel from'),
),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -122,10 +135,12 @@ export class PrivateCommand extends Subcommand {
}, },
{ {
id: coordinator, id: coordinator,
allow: [PermissionsBitField.Flags.SendMessages, allow: [
PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.ViewChannel,
PermissionsBitField.Flags.Connect, PermissionsBitField.Flags.Connect,
PermissionsBitField.Flags.MuteMembers], PermissionsBitField.Flags.MuteMembers,
],
}, },
], ],
}); });
@ -150,8 +165,10 @@ export class PrivateCommand extends Subcommand {
}, },
{ {
id: coordinator, id: coordinator,
allow: [PermissionsBitField.Flags.SendMessages, allow: [
PermissionsBitField.Flags.ViewChannel], PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel,
],
}, },
], ],
}); });
@ -173,8 +190,10 @@ export class PrivateCommand extends Subcommand {
}, },
{ {
id: coordinator, id: coordinator,
allow: [PermissionsBitField.Flags.SendMessages, allow: [
PermissionsBitField.Flags.ViewChannel], PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel,
],
}, },
], ],
}); });
@ -240,21 +259,23 @@ export class PrivateCommand extends Subcommand {
if (user === null) { if (user === null) {
if (channel.type !== ChannelType.GuildText) { if (channel.type !== ChannelType.GuildText) {
await interaction.editReply({ await interaction.editReply({
content: 'Please make sure you ran this command in the original private text channel!', content:
'Please make sure you ran this command in the original private text channel!',
}); });
return; return;
} }
if (channel.parentId !== IDs.categories.private) { if (channel.parentId !== IDs.categories.private) {
await interaction.editReply({ await interaction.editReply({
content: 'Please make sure you ran this command in the original private text channel!', content:
'Please make sure you ran this command in the original private text channel!',
}); });
return; return;
} }
if (channel.topic === null) { if (channel.topic === null) {
await interaction.editReply({ await interaction.editReply({
content: 'There was an error with this channel\'s topic!', content: "There was an error with this channel's topic!",
}); });
return; return;
} }
@ -265,15 +286,18 @@ export class PrivateCommand extends Subcommand {
const vcId = topic[topic.indexOf(coordinator) + 1]; const vcId = topic[topic.indexOf(coordinator) + 1];
const voiceChannel = guild.channels.cache.get(vcId); const voiceChannel = guild.channels.cache.get(vcId);
if (voiceChannel !== undefined if (
&& voiceChannel.parentId === IDs.categories.private) { voiceChannel !== undefined &&
voiceChannel.parentId === IDs.categories.private
) {
await voiceChannel.delete(); await voiceChannel.delete();
} }
return; return;
} }
const category = guild.channels.cache const category = guild.channels.cache.get(IDs.categories.private) as
.get(IDs.categories.private) as CategoryChannel | undefined; | CategoryChannel
| undefined;
if (category === undefined) { if (category === undefined) {
await interaction.editReply({ await interaction.editReply({
@ -282,7 +306,9 @@ export class PrivateCommand extends Subcommand {
return; return;
} }
const textChannels = category.children.cache.filter((c) => c.type === ChannelType.GuildText); const textChannels = category.children.cache.filter(
(c) => c.type === ChannelType.GuildText,
);
textChannels.forEach((c) => { textChannels.forEach((c) => {
const textChannel = c as TextChannel; const textChannel = c as TextChannel;
// Checks if the channel topic has the user's snowflake // Checks if the channel topic has the user's snowflake
@ -291,8 +317,10 @@ export class PrivateCommand extends Subcommand {
const vcId = topic[topic.indexOf(coordinator) + 1]; const vcId = topic[topic.indexOf(coordinator) + 1];
const voiceChannel = guild.channels.cache.get(vcId); const voiceChannel = guild.channels.cache.get(vcId);
if (voiceChannel !== undefined if (
&& voiceChannel.parentId === IDs.categories.private) { voiceChannel !== undefined &&
voiceChannel.parentId === IDs.categories.private
) {
voiceChannel.delete(); voiceChannel.delete();
} }
textChannel.delete(); textChannel.delete();
@ -333,19 +361,25 @@ export class PrivateCommand extends Subcommand {
} }
private checkPrivate(user: Snowflake, coordinator: string, guild: Guild) { private checkPrivate(user: Snowflake, coordinator: string, guild: Guild) {
const category = guild.channels.cache const category = guild.channels.cache.get(IDs.categories.private) as
.get(IDs.categories.private) as CategoryChannel | undefined; | CategoryChannel
| undefined;
if (category === undefined) { if (category === undefined) {
return true; return true;
} }
const textChannels = category.children.cache.filter((c) => c.type === ChannelType.GuildText); const textChannels = category.children.cache.filter(
(c) => c.type === ChannelType.GuildText,
);
let exists = false; let exists = false;
textChannels.forEach((c) => { textChannels.forEach((c) => {
const textChannel = c as TextChannel; const textChannel = c as TextChannel;
// Checks if the channel topic has the user's snowflake // Checks if the channel topic has the user's snowflake
if (textChannel.topic?.includes(user) && textChannel.topic?.includes(coordinator)) { if (
textChannel.topic?.includes(user) &&
textChannel.topic?.includes(coordinator)
) {
exists = true; exists = true;
} }
}); });

View File

@ -36,9 +36,7 @@ export class BalanceCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) => builder.setName(this.name).setDescription(this.description),
.setName(this.name)
.setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -114,10 +112,11 @@ export class BalanceCommand extends Command {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor('#00ff7d') .setColor('#00ff7d')
.setAuthor({ name: `${member.displayName}'s Account`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
.addFields( name: `${member.displayName}'s Account`,
{ name: 'Balance', value: `${balance.balance} ARA` }, iconURL: `${user.displayAvatarURL()}`,
); })
.addFields({ name: 'Balance', value: `${balance.balance} ARA` });
info.success = true; info.success = true;
info.embeds.push(embed); info.embeds.push(embed);

View File

@ -19,12 +19,7 @@
import { Command, RegisterBehavior } from '@sapphire/framework'; import { Command, RegisterBehavior } from '@sapphire/framework';
import { Time } from '@sapphire/time-utilities'; import { Time } from '@sapphire/time-utilities';
import type { import type { User, Guild, GuildMember, Message } from 'discord.js';
User,
Guild,
GuildMember,
Message,
} from 'discord.js';
import { updateUser } from '#utils/database/dbExistingUser'; import { updateUser } from '#utils/database/dbExistingUser';
import { daily, getLastDaily } from '#utils/database/economy'; import { daily, getLastDaily } from '#utils/database/economy';
import { EmbedBuilder } from 'discord.js'; import { EmbedBuilder } from 'discord.js';
@ -42,9 +37,7 @@ export class DailyCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) => builder.setName(this.name).setDescription(this.description),
.setName(this.name)
.setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -112,9 +105,12 @@ export class DailyCommand extends Command {
const lastDaily = await getLastDaily(user.id); const lastDaily = await getLastDaily(user.id);
if (lastDaily !== null if (
&& (new Date().getTime() - lastDaily.time.getTime()) < time) { lastDaily !== null &&
info.message = 'You have already claimed your daily, come back later to claim it!'; new Date().getTime() - lastDaily.time.getTime() < time
) {
info.message =
'You have already claimed your daily, come back later to claim it!';
return info; return info;
} }
@ -136,8 +132,15 @@ export class DailyCommand extends Command {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor('#00ff7d') .setColor('#00ff7d')
.setAuthor({ name: 'Daily Reward', iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
.addFields({ name: 'Collected', value: `${amount} ARA`, inline: bonus > 0 }); name: 'Daily Reward',
iconURL: `${user.displayAvatarURL()}`,
})
.addFields({
name: 'Collected',
value: `${amount} ARA`,
inline: bonus > 0,
});
if (bonus > 0) { if (bonus > 0) {
embed.addFields( embed.addFields(

View File

@ -36,19 +36,29 @@ export class BalanceCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('The user to give the money to') .addUserOption((option) =>
.setRequired(true)) option
.addIntegerOption((option) => option.setName('amount') .setName('user')
.setDescription('The amount to give to the user') .setDescription('The user to give the money to')
.setMinValue(1) .setRequired(true),
.setRequired(true)) )
.addStringOption((option) => option.setName('reason') .addIntegerOption((option) =>
.setDescription('The reason/reference for the transaction') option
.setRequired(true)), .setName('amount')
.setDescription('The amount to give to the user')
.setMinValue(1)
.setRequired(true),
)
.addStringOption((option) =>
option
.setName('reason')
.setDescription('The reason/reference for the transaction')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -133,7 +143,13 @@ export class BalanceCommand extends Command {
} }
} }
private async pay(user: User, recipient: User, amount: number, reason: string, guild: Guild) { private async pay(
user: User,
recipient: User,
amount: number,
reason: string,
guild: Guild,
) {
const info = { const info = {
message: '', message: '',
embeds: [] as EmbedBuilder[], embeds: [] as EmbedBuilder[],
@ -142,8 +158,9 @@ export class BalanceCommand extends Command {
// Check the amount to be paid is greater than 0 // Check the amount to be paid is greater than 0
if (amount < 1) { if (amount < 1) {
info.message = 'You need to actually give money, you can\'t send nothing or try to break the ' info.message =
+ 'economy 😭'; "You need to actually give money, you can't send nothing or try to break the " +
'economy 😭';
return info; return info;
} }
@ -166,7 +183,7 @@ export class BalanceCommand extends Command {
const balance = await getBalance(user.id); const balance = await getBalance(user.id);
if (balance.balance < amount) { if (balance.balance < amount) {
info.message = 'You don\'t have enough money to send!'; info.message = "You don't have enough money to send!";
return info; return info;
} }
@ -174,7 +191,10 @@ export class BalanceCommand extends Command {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor('#00ff7d') .setColor('#00ff7d')
.setAuthor({ name: `Transfer to ${recipientMember.displayName}`, iconURL: `${recipientMember.displayAvatarURL()}` }) .setAuthor({
name: `Transfer to ${recipientMember.displayName}`,
iconURL: `${recipientMember.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'From', value: `${user}`, inline: true }, { name: 'From', value: `${user}`, inline: true },
{ name: 'To', value: `${recipient}`, inline: true }, { name: 'To', value: `${recipient}`, inline: true },
@ -186,12 +206,14 @@ export class BalanceCommand extends Command {
info.embeds.push(embed); info.embeds.push(embed);
// Log the payment in the server // Log the payment in the server
let logChannel = guild.channels.cache let logChannel = guild.channels.cache.get(IDs.channels.logs.economy) as
.get(IDs.channels.logs.economy) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
logChannel = await guild.channels logChannel = (await guild.channels.fetch(IDs.channels.logs.economy)) as
.fetch(IDs.channels.logs.economy) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
this.container.logger.error('Pay Error: Could not fetch log channel'); this.container.logger.error('Pay Error: Could not fetch log channel');
return info; return info;
@ -199,9 +221,7 @@ export class BalanceCommand extends Command {
} }
const logEmbed = new EmbedBuilder(embed.data); const logEmbed = new EmbedBuilder(embed.data);
logEmbed logEmbed.setTimestamp().setFooter({ text: `ID: ${user.id}` });
.setTimestamp()
.setFooter({ text: `ID: ${user.id}` });
await logChannel.send({ embeds: [logEmbed] }); await logChannel.send({ embeds: [logEmbed] });
return info; return info;
} }

View File

@ -35,9 +35,7 @@ export class N1984Command extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) => builder.setName(this.name).setDescription(this.description),
.setName(this.name)
.setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -54,8 +52,10 @@ export class N1984Command extends Command {
// Creates the embed for the 1984 reaction // Creates the embed for the 1984 reaction
// Add a 1 in 1000 chance of Dantas literally making ARA 1984 // Add a 1 in 1000 chance of Dantas literally making ARA 1984
const random1984 = Math.random() < 0.001 ? 'https://c.tenor.com/0BwU0BjWYX4AAAAC/arthuria-dantas.gif' const random1984 =
: N1984[Math.floor(Math.random() * N1984.length)]; Math.random() < 0.001
? 'https://c.tenor.com/0BwU0BjWYX4AAAAC/arthuria-dantas.gif'
: N1984[Math.floor(Math.random() * N1984.length)];
const n1984Embed = new EmbedBuilder() const n1984Embed = new EmbedBuilder()
.setColor('#ffffff') .setColor('#ffffff')
.setTitle(`${user.username} is happy!`) .setTitle(`${user.username} is happy!`)

View File

@ -37,7 +37,7 @@ export class CringeCommand extends Command {
(builder) => builder.setName(this.name).setDescription(this.description), (builder) => builder.setName(this.name).setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
} },
); );
} }

View File

@ -34,9 +34,7 @@ export class HappyCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) => builder.setName(this.name).setDescription(this.description),
.setName(this.name)
.setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },

View File

@ -34,12 +34,16 @@ export class HugCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User you want to hug') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User you want to hug')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -61,9 +65,15 @@ export class HugCommand extends Command {
.setColor('#0099ff') .setColor('#0099ff')
.setTitle(`Hug from ${hugger.username}`) .setTitle(`Hug from ${hugger.username}`)
.setImage(randomHug) .setImage(randomHug)
.setFooter({ text: `Amount of hugs given from ${hugger.username} to you: ${count}` }); .setFooter({
text: `Amount of hugs given from ${hugger.username} to you: ${count}`,
});
// Send the hug // Send the hug
await interaction.reply({ content: `${user}`, embeds: [hugEmbed], fetchReply: true }); await interaction.reply({
content: `${user}`,
embeds: [hugEmbed],
fetchReply: true,
});
} }
} }

View File

@ -34,12 +34,16 @@ export class KillCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User you want to kill') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User you want to kill')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -66,9 +70,15 @@ export class KillCommand extends Command {
.setColor('#ff0000') .setColor('#ff0000')
.setTitle(`Kill from ${sender.username}`) .setTitle(`Kill from ${sender.username}`)
.setImage(randomKill) .setImage(randomKill)
.setFooter({ text: `Amount of kills from ${sender.username} to you: ${count}` }); .setFooter({
text: `Amount of kills from ${sender.username} to you: ${count}`,
});
// Send the kill // Send the kill
await interaction.reply({ content: `${user}`, embeds: [killEmbed], fetchReply: true }); await interaction.reply({
content: `${user}`,
embeds: [killEmbed],
fetchReply: true,
});
} }
} }

View File

@ -34,12 +34,16 @@ export class PokeCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User you want to poke') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User you want to poke')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -61,9 +65,15 @@ export class PokeCommand extends Command {
.setColor('#0099ff') .setColor('#0099ff')
.setTitle(`Poke from ${sender.username}`) .setTitle(`Poke from ${sender.username}`)
.setImage(randomPoke) .setImage(randomPoke)
.setFooter({ text: `Amount of pokes from ${sender.username} to you: ${count}` }); .setFooter({
text: `Amount of pokes from ${sender.username} to you: ${count}`,
});
// Send the poke // Send the poke
await interaction.reply({ content: `${user}`, embeds: [pokeEmbed], fetchReply: true }); await interaction.reply({
content: `${user}`,
embeds: [pokeEmbed],
fetchReply: true,
});
} }
} }

View File

@ -34,9 +34,7 @@ export class SadCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) => builder.setName(this.name).setDescription(this.description),
.setName(this.name)
.setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },

View File

@ -34,9 +34,7 @@ export class ShrugCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) => builder.setName(this.name).setDescription(this.description),
.setName(this.name)
.setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },

View File

@ -18,13 +18,7 @@
*/ */
import { Args, Command, RegisterBehavior } from '@sapphire/framework'; import { Args, Command, RegisterBehavior } from '@sapphire/framework';
import type { import type { User, Message, Snowflake, TextChannel, Guild } from 'discord.js';
User,
Message,
Snowflake,
TextChannel,
Guild,
} from 'discord.js';
import { EmbedBuilder } from 'discord.js'; import { EmbedBuilder } from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
import { addBan, checkBan } from '#utils/database/ban'; import { addBan, checkBan } from '#utils/database/ban';
@ -44,15 +38,22 @@ export class BanCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to ban') .addUserOption((option) =>
.setRequired(true)) option
.addStringOption((option) => option.setName('reason') .setName('user')
.setDescription('Note about the user') .setDescription('User to ban')
.setRequired(true)), .setRequired(true),
)
.addStringOption((option) =>
option
.setName('reason')
.setDescription('Note about the user')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -114,8 +115,10 @@ export class BanCommand extends Command {
if (message.channel.id !== IDs.channels.restricted.moderators) { if (message.channel.id !== IDs.channels.restricted.moderators) {
await message.react('❌'); await message.react('❌');
await message.reply(`You can only run this command in <#${IDs.channels.restricted.moderators}> ` await message.reply(
+ 'or alternatively use the slash command!'); `You can only run this command in <#${IDs.channels.restricted.moderators}> ` +
'or alternatively use the slash command!',
);
return; return;
} }
@ -125,7 +128,12 @@ export class BanCommand extends Command {
await message.react(ban.success ? '✅' : '❌'); await message.react(ban.success ? '✅' : '❌');
} }
private async ban(userId: Snowflake, modId: Snowflake, reason: string, guild: Guild) { private async ban(
userId: Snowflake,
modId: Snowflake,
reason: string,
guild: Guild,
) {
const info = { const info = {
message: '', message: '',
success: false, success: false,
@ -134,7 +142,7 @@ export class BanCommand extends Command {
let user = guild.client.users.cache.get(userId); let user = guild.client.users.cache.get(userId);
if (user === undefined) { if (user === undefined) {
user = await guild.client.users.fetch(userId) as User; user = (await guild.client.users.fetch(userId)) as User;
} }
// Gets mod's GuildMember // Gets mod's GuildMember
@ -158,8 +166,7 @@ export class BanCommand extends Command {
let member = guild.members.cache.get(userId); let member = guild.members.cache.get(userId);
if (member === undefined) { if (member === undefined) {
member = await guild.members.fetch(userId) member = await guild.members.fetch(userId).catch(() => undefined);
.catch(() => undefined);
} }
if (member !== undefined) { if (member !== undefined) {
@ -172,8 +179,11 @@ export class BanCommand extends Command {
await updateUser(member); await updateUser(member);
// Send DM for reason of ban // Send DM for reason of ban
await member.send(`You have been banned from ARA for: ${reason}` await member
+ '\n\nhttps://vbcamp.org/ARA') .send(
`You have been banned from ARA for: ${reason}` +
'\n\nhttps://vbcamp.org/ARA',
)
.catch(() => {}); .catch(() => {});
// Ban the user // Ban the user
@ -193,12 +203,14 @@ export class BanCommand extends Command {
info.success = true; info.success = true;
// Log the ban // Log the ban
let logChannel = guild.channels.cache let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
.get(IDs.channels.logs.restricted) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
logChannel = await guild.channels logChannel = (await guild.channels.fetch(
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined; IDs.channels.logs.restricted,
)) as TextChannel | undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
this.container.logger.error('Ban Error: Could not fetch log channel'); this.container.logger.error('Ban Error: Could not fetch log channel');
info.message = `${user} has been banned. This hasn't been logged in a text channel as log channel could not be found`; info.message = `${user} has been banned. This hasn't been logged in a text channel as log channel could not be found`;
@ -208,7 +220,10 @@ export class BanCommand extends Command {
const log = new EmbedBuilder() const log = new EmbedBuilder()
.setColor('#FF0000') .setColor('#FF0000')
.setAuthor({ name: `Banned ${user.tag}`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
name: `Banned ${user.tag}`,
iconURL: `${user.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'User', value: `${user}`, inline: true }, { name: 'User', value: `${user}`, inline: true },
{ name: 'Moderator', value: `${mod}`, inline: true }, { name: 'Moderator', value: `${mod}`, inline: true },

View File

@ -19,12 +19,7 @@
import { Args, Command, RegisterBehavior } from '@sapphire/framework'; import { Args, Command, RegisterBehavior } from '@sapphire/framework';
import { Duration, DurationFormatter } from '@sapphire/time-utilities'; import { Duration, DurationFormatter } from '@sapphire/time-utilities';
import type { import type { User, Snowflake, TextChannel, Guild } from 'discord.js';
User,
Snowflake,
TextChannel,
Guild,
} from 'discord.js';
import { EmbedBuilder, Message } from 'discord.js'; import { EmbedBuilder, Message } from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
import { addTempBan, checkTempBan } from '#utils/database/tempBan'; import { addTempBan, checkTempBan } from '#utils/database/tempBan';
@ -43,18 +38,28 @@ export class TempBanCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to ban') .addUserOption((option) =>
.setRequired(true)) option
.addStringOption((option) => option.setName('duration') .setName('user')
.setDescription('How long to ban the user for') .setDescription('User to ban')
.setRequired(true)) .setRequired(true),
.addStringOption((option) => option.setName('reason') )
.setDescription('Note about the user') .addStringOption((option) =>
.setRequired(true)), option
.setName('duration')
.setDescription('How long to ban the user for')
.setRequired(true),
)
.addStringOption((option) =>
option
.setName('reason')
.setDescription('Note about the user')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -140,8 +145,10 @@ export class TempBanCommand extends Command {
if (message.channel.id !== IDs.channels.restricted.moderators) { if (message.channel.id !== IDs.channels.restricted.moderators) {
await message.react('❌'); await message.react('❌');
await message.reply(`You can only run this command in <#${IDs.channels.restricted.moderators}> ` await message.reply(
+ 'or alternatively use the slash command!'); `You can only run this command in <#${IDs.channels.restricted.moderators}> ` +
'or alternatively use the slash command!',
);
return; return;
} }
@ -197,7 +204,7 @@ export class TempBanCommand extends Command {
let user = guild.client.users.cache.get(userId); let user = guild.client.users.cache.get(userId);
if (user === undefined) { if (user === undefined) {
user = await guild.client.users.fetch(userId) as User; user = (await guild.client.users.fetch(userId)) as User;
} }
// Gets mod's GuildMember // Gets mod's GuildMember
@ -221,8 +228,7 @@ export class TempBanCommand extends Command {
let member = guild.members.cache.get(userId); let member = guild.members.cache.get(userId);
if (member === undefined) { if (member === undefined) {
member = await guild.members.fetch(userId) member = await guild.members.fetch(userId).catch(() => undefined);
.catch(() => undefined);
} }
if (member !== undefined) { if (member !== undefined) {
@ -235,8 +241,11 @@ export class TempBanCommand extends Command {
await updateUser(member); await updateUser(member);
// Send DM for reason of ban // Send DM for reason of ban
await member.send(`You have been temporarily banned from ARA for ${banLength}. Reason: ${reason}` await member
+ '\n\nhttps://vbcamp.org/ARA') .send(
`You have been temporarily banned from ARA for ${banLength}. Reason: ${reason}` +
'\n\nhttps://vbcamp.org/ARA',
)
.catch(() => {}); .catch(() => {});
// Ban the user // Ban the user
@ -249,32 +258,44 @@ export class TempBanCommand extends Command {
await addTempBan(userId, modId, time.fromNow, reason); await addTempBan(userId, modId, time.fromNow, reason);
// Create scheduled task to unban // Create scheduled task to unban
this.container.tasks.create('tempBan', { this.container.tasks.create(
userId: user.id, 'tempBan',
guildId: guild.id, {
}, time.offset); userId: user.id,
guildId: guild.id,
},
time.offset,
);
info.message = `${user} has been temporarily banned for ${banLength}.`; info.message = `${user} has been temporarily banned for ${banLength}.`;
info.success = true; info.success = true;
// Log the ban // Log the ban
let logChannel = guild.channels.cache let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
.get(IDs.channels.logs.restricted) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
logChannel = await guild.channels logChannel = (await guild.channels.fetch(
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined; IDs.channels.logs.restricted,
)) as TextChannel | undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
this.container.logger.error('Temp Ban Error: Could not fetch log channel'); this.container.logger.error(
info.message = `${user} has been temporarily banned for ${banLength}. ` 'Temp Ban Error: Could not fetch log channel',
+ 'This hasn\'t been logged in a text channel as log channel could not be found'; );
info.message =
`${user} has been temporarily banned for ${banLength}. ` +
"This hasn't been logged in a text channel as log channel could not be found";
return info; return info;
} }
} }
const log = new EmbedBuilder() const log = new EmbedBuilder()
.setColor('#FF0000') .setColor('#FF0000')
.setAuthor({ name: `Temp Banned ${user.tag}`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
name: `Temp Banned ${user.tag}`,
iconURL: `${user.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'User', value: `${user}`, inline: true }, { name: 'User', value: `${user}`, inline: true },
{ name: 'Moderator', value: `${mod}`, inline: true }, { name: 'Moderator', value: `${mod}`, inline: true },

View File

@ -45,12 +45,16 @@ export class UnbanCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to unban') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to unban')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -162,13 +166,16 @@ export class UnbanCommand extends Command {
await addEmptyUser(user.id); await addEmptyUser(user.id);
// Add missing ban // Add missing ban
await addBan(userId, modId, `(Mod who banned is not accurate) - ${reason}`); await addBan(
userId,
modId,
`(Mod who banned is not accurate) - ${reason}`,
);
dbBan = true; dbBan = true;
} }
// Unban the user // Unban the user
await guild.members.unban(user) await guild.members.unban(user).catch(() => {});
.catch(() => {});
if (dbBan) { if (dbBan) {
// Add unban to database // Add unban to database
@ -181,12 +188,14 @@ export class UnbanCommand extends Command {
info.success = true; info.success = true;
// Log unban // Log unban
let logChannel = guild.channels.cache let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
.get(IDs.channels.logs.restricted) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
logChannel = await guild.channels logChannel = (await guild.channels.fetch(
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined; IDs.channels.logs.restricted,
)) as TextChannel | undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
this.container.logger.error('Ban Error: Could not fetch log channel'); this.container.logger.error('Ban Error: Could not fetch log channel');
info.message = `${user} has been banned. This hasn't been logged in a text channel as log channel could not be found`; info.message = `${user} has been banned. This hasn't been logged in a text channel as log channel could not be found`;
@ -196,7 +205,10 @@ export class UnbanCommand extends Command {
const log = new EmbedBuilder() const log = new EmbedBuilder()
.setColor('#28A745') .setColor('#28A745')
.setAuthor({ name: `Unbanned ${user.tag}`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
name: `Unbanned ${user.tag}`,
iconURL: `${user.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'User', value: `${user}`, inline: true }, { name: 'User', value: `${user}`, inline: true },
{ name: 'Moderator', value: `${mod}`, inline: true }, { name: 'Moderator', value: `${mod}`, inline: true },

View File

@ -56,16 +56,28 @@ export class DiversityCommand extends Subcommand {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Subcommand.Registry) { public override registerApplicationCommands(registry: Subcommand.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addSubcommand((command) => command.setName('role') .setDescription(this.description)
.setDescription('Gives/removes the diversity role') .addSubcommand((command) =>
.addUserOption((option) => option.setName('user') command
.setDescription('User to give/remove diversity to') .setName('role')
.setRequired(true))) .setDescription('Gives/removes the diversity role')
.addSubcommand((command) => command.setName('toggleopen') .addUserOption((option) =>
.setDescription('Toggles read-only for vegans in diversity section')), option
.setName('user')
.setDescription('User to give/remove diversity to')
.setRequired(true),
),
)
.addSubcommand((command) =>
command
.setName('toggleopen')
.setDescription(
'Toggles read-only for vegans in diversity section',
),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -120,11 +132,14 @@ export class DiversityCommand extends Subcommand {
} }
// Checks if the channel is open // Checks if the channel is open
const open = channel.permissionsFor(IDs.roles.vegan.vegan)! const open = channel
.permissionsFor(IDs.roles.vegan.vegan)!
.has([PermissionsBitField.Flags.SendMessages]); .has([PermissionsBitField.Flags.SendMessages]);
// Toggle send message in channel // Toggle send message in channel
await channelText.permissionOverwrites.edit(IDs.roles.vegan.vegan, { SendMessages: !open }); await channelText.permissionOverwrites.edit(IDs.roles.vegan.vegan, {
SendMessages: !open,
});
await interaction.reply({ await interaction.reply({
content: `${!open ? 'Opened' : 'Closed'} this channel.`, content: `${!open ? 'Opened' : 'Closed'} this channel.`,
@ -132,7 +147,9 @@ export class DiversityCommand extends Subcommand {
}); });
} }
public async roleCommand(interaction: Subcommand.ChatInputCommandInteraction) { public async roleCommand(
interaction: Subcommand.ChatInputCommandInteraction,
) {
// TODO add database updates // TODO add database updates
// Get the arguments // Get the arguments
const user = interaction.options.getUser('user'); const user = interaction.options.getUser('user');
@ -181,7 +198,8 @@ export class DiversityCommand extends Subcommand {
content: `Gave ${user} the ${diversity.name} role!`, content: `Gave ${user} the ${diversity.name} role!`,
fetchReply: true, fetchReply: true,
}); });
await user.send(`You have been given the ${diversity.name} role by ${mod}!`) await user
.send(`You have been given the ${diversity.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
} }
@ -200,7 +218,9 @@ export class DiversityCommand extends Subcommand {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Diversity coordinator not found! Try again or contact a developer!'); await message.reply(
'Diversity coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -235,7 +255,8 @@ export class DiversityCommand extends Subcommand {
await message.reply({ await message.reply({
content: `Gave ${user} the ${diversity.name} role!`, content: `Gave ${user} the ${diversity.name} role!`,
}); });
await user.send(`You have been given the ${diversity.name} role by ${mod}!`) await user
.send(`You have been given the ${diversity.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
} }
@ -243,7 +264,9 @@ export class DiversityCommand extends Subcommand {
} }
private async threadManager(member: Snowflake, add: boolean) { private async threadManager(member: Snowflake, add: boolean) {
const thread = await container.client.channels.fetch(IDs.channels.diversity.diversity); const thread = await container.client.channels.fetch(
IDs.channels.diversity.diversity,
);
if (thread === null) { if (thread === null) {
return; return;
} }

View File

@ -38,12 +38,16 @@ export class MoveAllCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addChannelOption((option) => option.setName('channel') .setDescription(this.description)
.setDescription('The channel to move everyone to') .addChannelOption((option) =>
.setRequired(true)), option
.setName('channel')
.setDescription('The channel to move everyone to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -59,8 +63,10 @@ export class MoveAllCommand extends Command {
await interaction.deferReply({ ephemeral: true }); await interaction.deferReply({ ephemeral: true });
if (channel.type !== ChannelType.GuildVoice if (
&& channel.type !== ChannelType.GuildStageVoice) { channel.type !== ChannelType.GuildVoice &&
channel.type !== ChannelType.GuildStageVoice
) {
await interaction.editReply({ await interaction.editReply({
content: 'The channel you provided is not a voice channel!', content: 'The channel you provided is not a voice channel!',
}); });
@ -100,8 +106,7 @@ export class MoveAllCommand extends Command {
const voice = guild.channels.cache.get(mod.voice.channelId); const voice = guild.channels.cache.get(mod.voice.channelId);
if (voice === undefined if (voice === undefined || !voice.isVoiceBased()) {
|| !voice.isVoiceBased()) {
await interaction.editReply({ await interaction.editReply({
content: 'Error fetching your current voice channel!', content: 'Error fetching your current voice channel!',
}); });
@ -138,7 +143,9 @@ export class MoveAllCommand extends Command {
if (mod.voice.channelId === null) { if (mod.voice.channelId === null) {
await message.react('❌'); await message.react('❌');
await message.reply('You need to be in a voice channel to run this command!'); await message.reply(
'You need to be in a voice channel to run this command!',
);
return; return;
} }
@ -150,8 +157,7 @@ export class MoveAllCommand extends Command {
const voice = guild.channels.cache.get(mod.voice.channelId); const voice = guild.channels.cache.get(mod.voice.channelId);
if (voice === undefined if (voice === undefined || !voice.isVoiceBased()) {
|| !voice.isVoiceBased()) {
await message.react('❌'); await message.react('❌');
await message.reply('Could not fetch current voice channel!'); await message.reply('Could not fetch current voice channel!');
return; return;
@ -161,7 +167,9 @@ export class MoveAllCommand extends Command {
member.voice.setChannel(channel.id); member.voice.setChannel(channel.id);
}); });
await message.reply(`Successfully moved ${voice.members.size} members to <#${channel.id}>!`); await message.reply(
`Successfully moved ${voice.members.size} members to <#${channel.id}>!`,
);
await message.react('✅'); await message.react('✅');
} }

View File

@ -34,15 +34,22 @@ export class RenameUserCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to change nickname') .addUserOption((option) =>
.setRequired(true)) option
.addStringOption((option) => option.setName('nickname') .setName('user')
.setDescription('The nickname to give the user') .setDescription('User to change nickname')
.setMaxLength(32)), .setRequired(true),
)
.addStringOption((option) =>
option
.setName('nickname')
.setDescription('The nickname to give the user')
.setMaxLength(32),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -85,7 +92,7 @@ export class RenameUserCommand extends Command {
await member.setNickname(nickname); await member.setNickname(nickname);
} catch { } catch {
await interaction.reply({ await interaction.reply({
content: 'Bot doesn\'t have permission to change the user\'s name!', content: "Bot doesn't have permission to change the user's name!",
ephemeral: true, ephemeral: true,
fetchReply: true, fetchReply: true,
}); });
@ -111,7 +118,7 @@ export class RenameUserCommand extends Command {
const nickname = args.finished ? null : await args.rest('string'); const nickname = args.finished ? null : await args.rest('string');
if ((nickname != null) && nickname.length > 32) { if (nickname != null && nickname.length > 32) {
await message.react('❌'); await message.react('❌');
await message.reply('Nickname is too long!'); await message.reply('Nickname is too long!');
return; return;
@ -121,7 +128,9 @@ export class RenameUserCommand extends Command {
await member.setNickname(nickname); await member.setNickname(nickname);
} catch { } catch {
await message.react('❌'); await message.react('❌');
await message.reply('Bot doesn\'t have permission to change the user\'s name!'); await message.reply(
"Bot doesn't have permission to change the user's name!",
);
return; return;
} }

View File

@ -29,15 +29,13 @@ import {
PermissionsBitField, PermissionsBitField,
time, time,
} from 'discord.js'; } from 'discord.js';
import type { import type { User, Message, TextChannel, Guild, Snowflake } from 'discord.js';
User,
Message,
TextChannel,
Guild,
Snowflake,
} from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
import { addEmptyUser, updateUser, fetchRoles } from '#utils/database/dbExistingUser'; import {
addEmptyUser,
updateUser,
fetchRoles,
} from '#utils/database/dbExistingUser';
import { restrict, checkActive } from '#utils/database/restriction'; import { restrict, checkActive } from '#utils/database/restriction';
import { randint } from '#utils/maths'; import { randint } from '#utils/maths';
import { blockedRolesAfterRestricted } from '#utils/blockedRoles'; import { blockedRolesAfterRestricted } from '#utils/blockedRoles';
@ -85,8 +83,7 @@ export async function restrictRun(
let member = guild.members.cache.get(userId); let member = guild.members.cache.get(userId);
if (member === undefined) { if (member === undefined) {
member = await guild.members.fetch(userId) member = await guild.members.fetch(userId).catch(() => undefined);
.catch(() => undefined);
} }
const restrictRoles = IDs.roles.restrictions.restricted; const restrictRoles = IDs.roles.restrictions.restricted;
@ -125,10 +122,12 @@ export async function restrictRun(
}, },
{ {
id: IDs.roles.staff.restricted, id: IDs.roles.staff.restricted,
allow: [PermissionsBitField.Flags.SendMessages, allow: [
PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.ViewChannel,
PermissionsBitField.Flags.Connect, PermissionsBitField.Flags.Connect,
PermissionsBitField.Flags.MuteMembers], PermissionsBitField.Flags.MuteMembers,
],
}, },
], ],
}); });
@ -153,8 +152,10 @@ export async function restrictRun(
}, },
{ {
id: IDs.roles.staff.restricted, id: IDs.roles.staff.restricted,
allow: [PermissionsBitField.Flags.SendMessages, allow: [
PermissionsBitField.Flags.ViewChannel], PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel,
],
}, },
], ],
}); });
@ -176,8 +177,10 @@ export async function restrictRun(
}, },
{ {
id: IDs.roles.staff.restricted, id: IDs.roles.staff.restricted,
allow: [PermissionsBitField.Flags.SendMessages, allow: [
PermissionsBitField.Flags.ViewChannel], PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel,
],
}, },
], ],
}); });
@ -215,8 +218,7 @@ export async function restrictRun(
} }
} }
if (member !== undefined if (member !== undefined && member.voice.channelId !== null) {
&& member.voice.channelId !== null) {
await member.voice.disconnect(); await member.voice.disconnect();
} }
@ -230,22 +232,24 @@ export async function restrictRun(
const dmEmbed = new EmbedBuilder() const dmEmbed = new EmbedBuilder()
.setColor('#FF6700') .setColor('#FF6700')
.setAuthor({ name: 'You\'ve been restricted!', iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
.addFields( name: "You've been restricted!",
{ name: 'Reason', value: reason }, iconURL: `${user.displayAvatarURL()}`,
) })
.addFields({ name: 'Reason', value: reason })
.setTimestamp(); .setTimestamp();
await user.send({ embeds: [dmEmbed] }) await user.send({ embeds: [dmEmbed] }).catch(() => {});
.catch(() => {});
// Log the ban // Log the ban
let logChannel = guild.channels.cache let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
.get(IDs.channels.logs.restricted) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
logChannel = await guild.channels logChannel = (await guild.channels.fetch(IDs.channels.logs.restricted)) as
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
container.logger.error('Restrict Error: Could not fetch log channel'); container.logger.error('Restrict Error: Could not fetch log channel');
info.message = `Restricted ${user} but could not find the log channel. This has been logged to the database.`; info.message = `Restricted ${user} but could not find the log channel. This has been logged to the database.`;
@ -255,7 +259,10 @@ export async function restrictRun(
const message = new EmbedBuilder() const message = new EmbedBuilder()
.setColor('#FF6700') .setColor('#FF6700')
.setAuthor({ name: `Restricted ${user.tag}`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
name: `Restricted ${user.tag}`,
iconURL: `${user.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'User', value: `${user}`, inline: true }, { name: 'User', value: `${user}`, inline: true },
{ name: 'Moderator', value: `${mod}`, inline: true }, { name: 'Moderator', value: `${mod}`, inline: true },
@ -283,15 +290,22 @@ export class RestrictCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to restrict') .addUserOption((option) =>
.setRequired(true)) option
.addStringOption((option) => option.setName('reason') .setName('user')
.setDescription('Reason for restricting the user') .setDescription('User to restrict')
.setRequired(true)), .setRequired(true),
)
.addStringOption((option) =>
option
.setName('reason')
.setDescription('Reason for restricting the user')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },

View File

@ -19,12 +19,7 @@
import { Args, Command, RegisterBehavior } from '@sapphire/framework'; import { Args, Command, RegisterBehavior } from '@sapphire/framework';
import { ChannelType, EmbedBuilder } from 'discord.js'; import { ChannelType, EmbedBuilder } from 'discord.js';
import type { import type { Message, TextChannel, Guild, Snowflake } from 'discord.js';
Message,
TextChannel,
Guild,
Snowflake,
} from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
import { getRestrictions } from '#utils/database/restriction'; import { getRestrictions } from '#utils/database/restriction';
import { checkStaff } from '#utils/checker'; import { checkStaff } from '#utils/checker';
@ -42,11 +37,15 @@ export class RestrictLogsCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to check restriction logs for')), .addUserOption((option) =>
option
.setName('user')
.setDescription('User to check restriction logs for'),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -72,8 +71,7 @@ export class RestrictLogsCommand extends Command {
let userId: Snowflake | null = null; let userId: Snowflake | null = null;
if (user !== undefined if (user !== undefined && user !== null) {
&& user !== null) {
userId = user.id; userId = user.id;
} }
@ -201,9 +199,11 @@ export class RestrictLogsCommand extends Command {
.setFooter({ text: `ID: ${userId}` }); .setFooter({ text: `ID: ${userId}` });
// Add up to 10 of the latest restrictions to the embed // Add up to 10 of the latest restrictions to the embed
for (let i = restrictions.length > 10 ? restrictions.length - 10 : 0; for (
let i = restrictions.length > 10 ? restrictions.length - 10 : 0;
i < restrictions.length; i < restrictions.length;
i += 1) { i += 1
) {
// Get mod names // Get mod names
let restMod = restrictions[i].modId; let restMod = restrictions[i].modId;
const restModMember = guild.members.cache.get(restMod); const restModMember = guild.members.cache.get(restMod);
@ -226,7 +226,9 @@ export class RestrictLogsCommand extends Command {
restTitle += 'Currently Restricted | '; restTitle += 'Currently Restricted | ';
} }
restTitle += `Date: <t:${Math.floor(restrictions[i].startTime.getTime() / 1000)}>`; restTitle += `Date: <t:${Math.floor(
restrictions[i].startTime.getTime() / 1000,
)}>`;
embed.addFields({ embed.addFields({
name: restTitle, name: restTitle,

View File

@ -35,15 +35,22 @@ export class RestrictToleranceCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to restrict') .addUserOption((option) =>
.setRequired(true)) option
.addStringOption((option) => option.setName('reason') .setName('user')
.setDescription('Reason for restricting the user') .setDescription('User to restrict')
.setRequired(true)), .setRequired(true),
)
.addStringOption((option) =>
option
.setName('reason')
.setDescription('Reason for restricting the user')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },

View File

@ -20,10 +20,7 @@
import { RegisterBehavior } from '@sapphire/framework'; import { RegisterBehavior } from '@sapphire/framework';
import { Subcommand } from '@sapphire/plugin-subcommands'; import { Subcommand } from '@sapphire/plugin-subcommands';
import type { TextChannel } from 'discord.js'; import type { TextChannel } from 'discord.js';
import { import { CategoryChannel, ChannelType } from 'discord.js';
CategoryChannel,
ChannelType,
} from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
export class RestrictToolsCommand extends Subcommand { export class RestrictToolsCommand extends Subcommand {
@ -35,9 +32,7 @@ export class RestrictToolsCommand extends Subcommand {
{ {
name: 'channel', name: 'channel',
type: 'group', type: 'group',
entries: [ entries: [{ name: 'delete', chatInputRun: 'deleteChannel' }],
{ name: 'delete', chatInputRun: 'deleteChannel' },
],
}, },
], ],
description: 'Tools for managing restrictions', description: 'Tools for managing restrictions',
@ -48,22 +43,34 @@ export class RestrictToolsCommand extends Subcommand {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Subcommand.Registry) { public override registerApplicationCommands(registry: Subcommand.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addSubcommandGroup((group) => group.setName('channel') .setDescription(this.description)
.setDescription('Manages restricted channels') .addSubcommandGroup((group) =>
.addSubcommand((command) => command.setName('delete') group
.setDescription('Deletes a restricted channel') .setName('channel')
.addUserOption((option) => option.setName('user') .setDescription('Manages restricted channels')
.setDescription('The user\'s channel to delete')))), .addSubcommand((command) =>
command
.setName('delete')
.setDescription('Deletes a restricted channel')
.addUserOption((option) =>
option
.setName('user')
.setDescription("The user's channel to delete"),
),
),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
); );
} }
public async deleteChannel(interaction: Subcommand.ChatInputCommandInteraction) { public async deleteChannel(
interaction: Subcommand.ChatInputCommandInteraction,
) {
// Get the arguments // Get the arguments
const user = interaction.options.getUser('user'); const user = interaction.options.getUser('user');
const { guild, channel } = interaction; const { guild, channel } = interaction;
@ -83,33 +90,35 @@ export class RestrictToolsCommand extends Subcommand {
if (user === null) { if (user === null) {
if (channel.type !== ChannelType.GuildText) { if (channel.type !== ChannelType.GuildText) {
await interaction.editReply({ await interaction.editReply({
content: 'Please make sure you ran this command in the original restricted text channel!', content:
'Please make sure you ran this command in the original restricted text channel!',
}); });
return; return;
} }
if (channel.parentId !== IDs.categories.restricted) { if (channel.parentId !== IDs.categories.restricted) {
await interaction.editReply({ await interaction.editReply({
content: 'Please make sure you ran this command in the original restricted text channel!', content:
'Please make sure you ran this command in the original restricted text channel!',
}); });
return; return;
} }
if ( if (
channel.id === IDs.channels.restricted.welcome channel.id === IDs.channels.restricted.welcome ||
|| channel.id === IDs.channels.restricted.moderators channel.id === IDs.channels.restricted.moderators ||
|| channel.id === IDs.channels.restricted.restricted channel.id === IDs.channels.restricted.restricted ||
|| channel.id === IDs.channels.restricted.tolerance channel.id === IDs.channels.restricted.tolerance
) { ) {
await interaction.editReply({ await interaction.editReply({
content: 'You can\'t run this command these channels!', content: "You can't run this command these channels!",
}); });
return; return;
} }
if (channel.topic === null) { if (channel.topic === null) {
await interaction.editReply({ await interaction.editReply({
content: 'There was an error with this channel\'s topic!', content: "There was an error with this channel's topic!",
}); });
return; return;
} }
@ -120,16 +129,19 @@ export class RestrictToolsCommand extends Subcommand {
const vcId = topic[3]; const vcId = topic[3];
const voiceChannel = guild.channels.cache.get(vcId); const voiceChannel = guild.channels.cache.get(vcId);
if (voiceChannel !== undefined if (
&& voiceChannel.parentId === IDs.categories.restricted) { voiceChannel !== undefined &&
voiceChannel.parentId === IDs.categories.restricted
) {
await voiceChannel.delete(); await voiceChannel.delete();
} }
return; return;
} }
const category = guild.channels.cache const category = guild.channels.cache.get(IDs.categories.restricted) as
.get(IDs.categories.restricted) as CategoryChannel | undefined; | CategoryChannel
| undefined;
if (category === undefined) { if (category === undefined) {
await interaction.editReply({ await interaction.editReply({
@ -138,7 +150,9 @@ export class RestrictToolsCommand extends Subcommand {
return; return;
} }
const textChannels = category.children.cache.filter((c) => c.type === ChannelType.GuildText); const textChannels = category.children.cache.filter(
(c) => c.type === ChannelType.GuildText,
);
textChannels.forEach((c) => { textChannels.forEach((c) => {
const textChannel = c as TextChannel; const textChannel = c as TextChannel;
// Checks if the channel topic has the user's snowflake // Checks if the channel topic has the user's snowflake
@ -147,8 +161,10 @@ export class RestrictToolsCommand extends Subcommand {
const vcId = topic[topic.indexOf(user?.id) + 1]; const vcId = topic[topic.indexOf(user?.id) + 1];
const voiceChannel = guild.channels.cache.get(vcId); const voiceChannel = guild.channels.cache.get(vcId);
if (voiceChannel !== undefined if (
&& voiceChannel.parentId === IDs.categories.restricted) { voiceChannel !== undefined &&
voiceChannel.parentId === IDs.categories.restricted
) {
voiceChannel.delete(); voiceChannel.delete();
} }
textChannel.delete(); textChannel.delete();

View File

@ -19,16 +19,14 @@
import { Args, Command, RegisterBehavior } from '@sapphire/framework'; import { Args, Command, RegisterBehavior } from '@sapphire/framework';
import { CategoryChannel, ChannelType, EmbedBuilder } from 'discord.js'; import { CategoryChannel, ChannelType, EmbedBuilder } from 'discord.js';
import type { import type { User, Message, TextChannel, Guild, Snowflake } from 'discord.js';
User,
Message,
TextChannel,
Guild,
Snowflake,
} from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
import { fetchRoles, addExistingUser } from '#utils/database/dbExistingUser'; import { fetchRoles, addExistingUser } from '#utils/database/dbExistingUser';
import { unRestrict, checkActive, unRestrictLegacy } from '#utils/database/restriction'; import {
unRestrict,
checkActive,
unRestrictLegacy,
} from '#utils/database/restriction';
export class UnRestrictCommand extends Command { export class UnRestrictCommand extends Command {
public constructor(context: Command.Context, options: Command.Options) { public constructor(context: Command.Context, options: Command.Options) {
@ -44,12 +42,16 @@ export class UnRestrictCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to unrestrict') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to unrestrict')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -105,7 +107,12 @@ export class UnRestrictCommand extends Command {
const channelRun = message.channel; const channelRun = message.channel;
const info = await this.unRestrictRun(user?.id, mod.id, guild, channelRun.id); const info = await this.unRestrictRun(
user?.id,
mod.id,
guild,
channelRun.id,
);
if (!info.runInVeganRestrict) { if (!info.runInVeganRestrict) {
await message.reply(info.message); await message.reply(info.message);
@ -151,12 +158,11 @@ export class UnRestrictCommand extends Command {
let member = guild.members.cache.get(userId); let member = guild.members.cache.get(userId);
if (member === undefined) { if (member === undefined) {
member = await guild.members.fetch(userId) member = await guild.members.fetch(userId).catch(() => undefined);
.catch(() => undefined);
} }
if (member === undefined) { if (member === undefined) {
info.message = 'Can\'t unrestrict the user as they are not on this server'; info.message = "Can't unrestrict the user as they are not on this server";
return info; return info;
} }
@ -192,14 +198,16 @@ export class UnRestrictCommand extends Command {
// Remove vegan restrict channels // Remove vegan restrict channels
if (member.roles.cache.has(IDs.roles.vegan.vegan)) { if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
const category = guild.channels.cache const category = guild.channels.cache.get(IDs.categories.restricted) as
.get(IDs.categories.restricted) as CategoryChannel | undefined; | CategoryChannel
| undefined;
let topic: string[]; let topic: string[];
if (category !== undefined) { if (category !== undefined) {
const textChannels = category.children.cache const textChannels = category.children.cache.filter(
.filter((c) => c.type === ChannelType.GuildText); (c) => c.type === ChannelType.GuildText,
);
textChannels.forEach((c) => { textChannels.forEach((c) => {
const textChannel = c as TextChannel; const textChannel = c as TextChannel;
// Checks if the channel topic has the user's snowflake // Checks if the channel topic has the user's snowflake
@ -211,8 +219,10 @@ export class UnRestrictCommand extends Command {
const vcId = topic[topic.indexOf(userId) + 1]; const vcId = topic[topic.indexOf(userId) + 1];
const voiceChannel = guild.channels.cache.get(vcId); const voiceChannel = guild.channels.cache.get(vcId);
if (voiceChannel !== undefined if (
&& voiceChannel.parentId === IDs.categories.restricted) { voiceChannel !== undefined &&
voiceChannel.parentId === IDs.categories.restricted
) {
voiceChannel.delete(); voiceChannel.delete();
} }
textChannel.delete(); textChannel.delete();
@ -224,14 +234,18 @@ export class UnRestrictCommand extends Command {
info.success = true; info.success = true;
// Log the ban // Log the ban
let logChannel = guild.channels.cache let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
.get(IDs.channels.logs.restricted) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
logChannel = await guild.channels logChannel = (await guild.channels.fetch(
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined; IDs.channels.logs.restricted,
)) as TextChannel | undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
this.container.logger.error('Restrict Error: Could not fetch log channel'); this.container.logger.error(
'Restrict Error: Could not fetch log channel',
);
info.message = `Unrestricted ${user} but could not find the log channel. This has been logged to the database.`; info.message = `Unrestricted ${user} but could not find the log channel. This has been logged to the database.`;
return info; return info;
} }
@ -239,7 +253,10 @@ export class UnRestrictCommand extends Command {
const message = new EmbedBuilder() const message = new EmbedBuilder()
.setColor('#28A745') .setColor('#28A745')
.setAuthor({ name: `Unrestricted ${user.tag}`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
name: `Unrestricted ${user.tag}`,
iconURL: `${user.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'User', value: `${user}`, inline: true }, { name: 'User', value: `${user}`, inline: true },
{ name: 'Moderator', value: `${mod}`, inline: true }, { name: 'Moderator', value: `${mod}`, inline: true },

View File

@ -36,12 +36,16 @@ export class SlowmodeCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addStringOption((option) => option.setName('duration') .setDescription(this.description)
.setDescription('Set the slowmode time') .addStringOption((option) =>
.setRequired(true)), option
.setName('duration')
.setDescription('Set the slowmode time')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -123,7 +127,9 @@ export class SlowmodeCommand extends Command {
return info; return info;
} }
info.message = `${channel} has now been set to a post every ${new DurationFormatter().format(time)}.`; info.message = `${channel} has now been set to a post every ${new DurationFormatter().format(
time,
)}.`;
return info; return info;
} }
} }

View File

@ -27,8 +27,9 @@ export class SoftMuteCommand extends Command {
...options, ...options,
name: 'softmute', name: 'softmute',
aliases: ['sm'], aliases: ['sm'],
description: 'Prevent a user from reacting to a message by giving ' description:
+ 'the soft mute role', 'Prevent a user from reacting to a message by giving ' +
'the soft mute role',
preconditions: ['ModOnly'], preconditions: ['ModOnly'],
}); });
} }
@ -36,12 +37,16 @@ export class SoftMuteCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to soft mute') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to soft mute')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },

View File

@ -75,36 +75,64 @@ export class SusCommand extends Subcommand {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Subcommand.Registry) { public override registerApplicationCommands(registry: Subcommand.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
// Subcommand to add a sus note .setDescription(this.description)
.addSubcommand((command) => command.setName('add') // Subcommand to add a sus note
.setDescription('Add a sus note about a user') .addSubcommand((command) =>
.addUserOption((option) => option.setName('user') command
.setDescription('User to add the note') .setName('add')
.setRequired(true)) .setDescription('Add a sus note about a user')
.addStringOption((option) => option.setName('note') .addUserOption((option) =>
.setDescription('Note about the user') option
.setRequired(true))) .setName('user')
// Subcommand to list sus notes .setDescription('User to add the note')
.addSubcommand((command) => command.setName('view') .setRequired(true),
.setDescription('View a sus note for a user') )
.addUserOption((option) => option.setName('user') .addStringOption((option) =>
.setDescription('User to view the note of') option
.setRequired(true))) .setName('note')
// Subcommand to remove a specific sus note .setDescription('Note about the user')
.addSubcommand((command) => command.setName('remove') .setRequired(true),
.setDescription('Remove a specific sus note') ),
.addIntegerOption((option) => option.setName('id') )
.setDescription('Sus note ID') // Subcommand to list sus notes
.setRequired(true))) .addSubcommand((command) =>
// Subcommand to remove all sus notes command
.addSubcommand((command) => command.setName('purge') .setName('view')
.setDescription('Remove all sus notes from a user') .setDescription('View a sus note for a user')
.addUserOption((option) => option.setName('user') .addUserOption((option) =>
.setDescription('User to remove the note from') option
.setRequired(true))), .setName('user')
.setDescription('User to view the note of')
.setRequired(true),
),
)
// Subcommand to remove a specific sus note
.addSubcommand((command) =>
command
.setName('remove')
.setDescription('Remove a specific sus note')
.addIntegerOption((option) =>
option
.setName('id')
.setDescription('Sus note ID')
.setRequired(true),
),
)
// Subcommand to remove all sus notes
.addSubcommand((command) =>
command
.setName('purge')
.setDescription('Remove all sus notes from a user')
.addUserOption((option) =>
option
.setName('user')
.setDescription('User to remove the note from')
.setRequired(true),
),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -202,7 +230,11 @@ export class SusCommand extends Subcommand {
.setThumbnail(user.displayAvatarURL()); .setThumbnail(user.displayAvatarURL());
// Add up to 10 of the latest sus notes to the embed // Add up to 10 of the latest sus notes to the embed
for (let i = notes.length > 10 ? notes.length - 10 : 0; i < notes.length; i += 1) { for (
let i = notes.length > 10 ? notes.length - 10 : 0;
i < notes.length;
i += 1
) {
// Get mod name // Get mod name
let mod = notes[i].modId; let mod = notes[i].modId;
const modMember = guild.members.cache.get(mod); const modMember = guild.members.cache.get(mod);
@ -212,7 +244,11 @@ export class SusCommand extends Subcommand {
// Add sus note to embed // Add sus note to embed
noteEmbed.addFields({ noteEmbed.addFields({
name: `Sus ID: ${notes[i].id} | Moderator: ${mod} | Date: <t:${Math.floor(notes[i].time.getTime() / 1000)}>`, name: `Sus ID: ${
notes[i].id
} | Moderator: ${mod} | Date: <t:${Math.floor(
notes[i].time.getTime() / 1000,
)}>`,
value: notes[i].note, value: notes[i].note,
}); });
} }
@ -285,22 +321,23 @@ export class SusCommand extends Subcommand {
.setTitle(`Sus note for ${userName}`) .setTitle(`Sus note for ${userName}`)
.setThumbnail(member.displayAvatarURL()) .setThumbnail(member.displayAvatarURL())
.addFields({ .addFields({
name: `ID: ${noteId} | Moderator: ${modName} | Date: <t:${Math.floor(note.time.getTime() / 1000)}>`, name: `ID: ${noteId} | Moderator: ${modName} | Date: <t:${Math.floor(
note.time.getTime() / 1000,
)}>`,
value: note.note, value: note.note,
}); });
// Create buttons to delete or cancel the deletion // Create buttons to delete or cancel the deletion
const buttons = new ActionRowBuilder<ButtonBuilder>() const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
.addComponents( new ButtonBuilder()
new ButtonBuilder() .setCustomId(`delete${noteId}`)
.setCustomId(`delete${noteId}`) .setLabel('Delete')
.setLabel('Delete') .setStyle(ButtonStyle.Danger),
.setStyle(ButtonStyle.Danger), new ButtonBuilder()
new ButtonBuilder() .setCustomId(`cancel${noteId}`)
.setCustomId(`cancel${noteId}`) .setLabel('Cancel')
.setLabel('Cancel') .setStyle(ButtonStyle.Secondary),
.setStyle(ButtonStyle.Secondary), );
);
// Sends the note to verify this note is to be deleted // Sends the note to verify this note is to be deleted
const message = await interaction.reply({ const message = await interaction.reply({
@ -350,7 +387,9 @@ export class SusCommand extends Subcommand {
}); });
} }
public async removeAllNotes(interaction: Subcommand.ChatInputCommandInteraction) { public async removeAllNotes(
interaction: Subcommand.ChatInputCommandInteraction,
) {
// Get the arguments // Get the arguments
const user = interaction.options.getUser('user', true); const user = interaction.options.getUser('user', true);
const { guild, channel } = interaction; const { guild, channel } = interaction;
@ -398,7 +437,11 @@ export class SusCommand extends Subcommand {
.setThumbnail(user.displayAvatarURL()); .setThumbnail(user.displayAvatarURL());
// Add up to 10 of the latest sus notes to the embed // Add up to 10 of the latest sus notes to the embed
for (let i = notes.length > 10 ? notes.length - 10 : 0; i < notes.length; i += 1) { for (
let i = notes.length > 10 ? notes.length - 10 : 0;
i < notes.length;
i += 1
) {
// Get mod name // Get mod name
let mod = notes[i].modId; let mod = notes[i].modId;
const modGuildMember = guild.members.cache.get(mod); const modGuildMember = guild.members.cache.get(mod);
@ -407,23 +450,26 @@ export class SusCommand extends Subcommand {
} }
// Add sus note to embed // Add sus note to embed
noteEmbed.addFields({ noteEmbed.addFields({
name: `Sus ID: ${notes[i].id} | Moderator: ${mod} | Date: <t:${Math.floor(notes[i].time.getTime() / 1000)}>`, name: `Sus ID: ${
notes[i].id
} | Moderator: ${mod} | Date: <t:${Math.floor(
notes[i].time.getTime() / 1000,
)}>`,
value: notes[i].note, value: notes[i].note,
}); });
} }
// Create buttons to delete or cancel the deletion // Create buttons to delete or cancel the deletion
const buttons = new ActionRowBuilder<ButtonBuilder>() const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
.addComponents( new ButtonBuilder()
new ButtonBuilder() .setCustomId(`delete${user.id}`)
.setCustomId(`delete${user.id}`) .setLabel('Delete')
.setLabel('Delete') .setStyle(ButtonStyle.Danger),
.setStyle(ButtonStyle.Danger), new ButtonBuilder()
new ButtonBuilder() .setCustomId(`cancel${user.id}`)
.setCustomId(`cancel${user.id}`) .setLabel('Cancel')
.setLabel('Cancel') .setStyle(ButtonStyle.Secondary),
.setStyle(ButtonStyle.Secondary), );
);
// Sends the note to verify this note is to be deleted // Sends the note to verify this note is to be deleted
const message = await interaction.reply({ const message = await interaction.reply({
@ -491,7 +537,9 @@ export class SusCommand extends Subcommand {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Moderator not found! Try again or contact a developer!'); await message.reply(
'Moderator not found! Try again or contact a developer!',
);
return; return;
} }

View File

@ -36,14 +36,21 @@ export class VCMuteCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to persistently mute') .addUserOption((option) =>
.setRequired(true)) option
.addStringOption((option) => option.setName('reason') .setName('user')
.setDescription('Reason for persistently muting the user')), .setDescription('User to persistently mute')
.setRequired(true),
)
.addStringOption((option) =>
option
.setName('reason')
.setDescription('Reason for persistently muting the user'),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -128,7 +135,9 @@ export class VCMuteCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Moderator not found! Try again or contact a developer!'); await message.reply(
'Moderator not found! Try again or contact a developer!',
);
return; return;
} }

View File

@ -18,12 +18,7 @@
*/ */
import { Args, Command } from '@sapphire/framework'; import { Args, Command } from '@sapphire/framework';
import type { import type { User, Message, Snowflake, Guild } from 'discord.js';
User,
Message,
Snowflake,
Guild,
} from 'discord.js';
import { addExistingUser, updateUser } from '#utils/database/dbExistingUser'; import { addExistingUser, updateUser } from '#utils/database/dbExistingUser';
import { addWarn } from '#utils/database/warnings'; import { addWarn } from '#utils/database/warnings';
@ -63,7 +58,9 @@ export class WarnCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Moderator not found! Try again or contact a developer!'); await message.reply(
'Moderator not found! Try again or contact a developer!',
);
return; return;
} }
@ -84,7 +81,12 @@ export class WarnCommand extends Command {
// await message.react('✅'); // await message.react('✅');
} }
private async warn(userId: Snowflake, modId: Snowflake, reason: string, guild: Guild) { private async warn(
userId: Snowflake,
modId: Snowflake,
reason: string,
guild: Guild,
) {
const info = { const info = {
message: '', message: '',
success: false, success: false,
@ -106,8 +108,7 @@ export class WarnCommand extends Command {
let member = guild.members.cache.get(userId); let member = guild.members.cache.get(userId);
if (member === undefined) { if (member === undefined) {
member = await guild.members.fetch(userId) member = await guild.members.fetch(userId).catch(() => undefined);
.catch(() => undefined);
} }
if (member === undefined) { if (member === undefined) {

View File

@ -25,7 +25,8 @@ import {
addStatUser, addStatUser,
checkActiveEvent, checkActiveEvent,
createEvent, createEvent,
createStat, endEvent, createStat,
endEvent,
getCurrentEvent, getCurrentEvent,
getStatFromLeader, getStatFromLeader,
getStatFromRole, getStatFromRole,
@ -69,14 +70,20 @@ export class OutreachCommand extends Subcommand {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Subcommand.Registry) { public override registerApplicationCommands(registry: Subcommand.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addSubcommandGroup((group) => group.setName('event') .setDescription(this.description)
.setDescription('Commands to do with outreach events') .addSubcommandGroup((group) =>
.addSubcommand((command) => command.setName('create') group
.setDescription('Start an outreach event')) .setName('event')
/* .setDescription('Commands to do with outreach events')
.addSubcommand((command) =>
command
.setName('create')
.setDescription('Start an outreach event'),
)
/*
TODO add this back at a later date TODO add this back at a later date
.addBooleanOption((option) => option.setName('start') .addBooleanOption((option) => option.setName('start')
@ -84,43 +91,96 @@ export class OutreachCommand extends Subcommand {
.addSubcommand((command) => command.setName('start') .addSubcommand((command) => command.setName('start')
.setDescription('Start an outreach event')) .setDescription('Start an outreach event'))
*/ */
.addSubcommand((command) => command.setName('end') .addSubcommand((command) =>
.setDescription('End an outreach event'))) command.setName('end').setDescription('End an outreach event'),
.addSubcommandGroup((group) => group.setName('group') ),
.setDescription('Commands to do with groups') )
.addSubcommand((command) => command.setName('create') .addSubcommandGroup((group) =>
.setDescription('Create a group for people doing activism') group
.addUserOption((option) => option.setName('leader') .setName('group')
.setDescription('This is the person leading the group') .setDescription('Commands to do with groups')
.setRequired(true))) .addSubcommand((command) =>
.addSubcommand((command) => command.setName('add') command
.setDescription('Add a person to the group') .setName('create')
.addUserOption((option) => option.setName('user') .setDescription('Create a group for people doing activism')
.setDescription('User to add to the group') .addUserOption((option) =>
.setRequired(true)) option
.addRoleOption((option) => option.setName('group') .setName('leader')
.setDescription('Group to add the user to'))) .setDescription('This is the person leading the group')
.addSubcommand((command) => command.setName('update') .setRequired(true),
.setDescription('Update the statistics for the group') ),
.addIntegerOption((option) => option.setName('vegan') )
.setDescription('How many said would go vegan?')) .addSubcommand((command) =>
.addIntegerOption((option) => option.setName('considered') command
.setDescription('How many seriously considered being vegan?')) .setName('add')
.addIntegerOption((option) => option.setName('anti-vegan') .setDescription('Add a person to the group')
.setDescription('How many people had anti-vegan viewpoints?')) .addUserOption((option) =>
.addIntegerOption((option) => option.setName('thanked') option
.setDescription('How many thanked you for the conversation?')) .setName('user')
.addIntegerOption((option) => option.setName('documentary') .setDescription('User to add to the group')
.setDescription('How many said they would watch a vegan documentary?')) .setRequired(true),
.addIntegerOption((option) => option.setName('educated') )
.setDescription('How many got educated on veganism or the animal industry?')))), .addRoleOption((option) =>
option
.setName('group')
.setDescription('Group to add the user to'),
),
)
.addSubcommand((command) =>
command
.setName('update')
.setDescription('Update the statistics for the group')
.addIntegerOption((option) =>
option
.setName('vegan')
.setDescription('How many said would go vegan?'),
)
.addIntegerOption((option) =>
option
.setName('considered')
.setDescription(
'How many seriously considered being vegan?',
),
)
.addIntegerOption((option) =>
option
.setName('anti-vegan')
.setDescription(
'How many people had anti-vegan viewpoints?',
),
)
.addIntegerOption((option) =>
option
.setName('thanked')
.setDescription(
'How many thanked you for the conversation?',
),
)
.addIntegerOption((option) =>
option
.setName('documentary')
.setDescription(
'How many said they would watch a vegan documentary?',
),
)
.addIntegerOption((option) =>
option
.setName('educated')
.setDescription(
'How many got educated on veganism or the animal industry?',
),
),
),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
); );
} }
public async eventCreate(interaction: Subcommand.ChatInputCommandInteraction) { public async eventCreate(
interaction: Subcommand.ChatInputCommandInteraction,
) {
// const start = interaction.options.getBoolean('start'); // const start = interaction.options.getBoolean('start');
const modUser = interaction.user; const modUser = interaction.user;
const { guild } = interaction; const { guild } = interaction;
@ -238,9 +298,10 @@ export class OutreachCommand extends Subcommand {
const activist = guild.channels.cache.get(IDs.channels.activism.activism); const activist = guild.channels.cache.get(IDs.channels.activism.activism);
if (activist === undefined if (activist === undefined || !activist.isTextBased()) {
|| !activist.isTextBased()) { await interaction.editReply(
await interaction.editReply('Event has now ended, but could not post statistics!'); 'Event has now ended, but could not post statistics!',
);
return; return;
} }
@ -249,11 +310,26 @@ export class OutreachCommand extends Subcommand {
.setAuthor({ name: 'Stats for Discord Outreach' }) .setAuthor({ name: 'Stats for Discord Outreach' })
.addFields( .addFields(
{ name: 'How many said would go vegan?', value: `${vegan}` }, { name: 'How many said would go vegan?', value: `${vegan}` },
{ name: 'How many seriously considered being vegan?', value: `${considered}` }, {
{ name: 'How many people had anti-vegan viewpoints?', value: `${antiVegan}` }, name: 'How many seriously considered being vegan?',
{ name: 'How many thanked you for the conversation?', value: `${thanked}` }, value: `${considered}`,
{ name: 'How many said they would watch a vegan documentary?', value: `${documentary}` }, },
{ name: 'How many got educated on veganism or the animal industry?', value: `${educated}` }, {
name: 'How many people had anti-vegan viewpoints?',
value: `${antiVegan}`,
},
{
name: 'How many thanked you for the conversation?',
value: `${thanked}`,
},
{
name: 'How many said they would watch a vegan documentary?',
value: `${documentary}`,
},
{
name: 'How many got educated on veganism or the animal industry?',
value: `${educated}`,
},
) )
.setTimestamp() .setTimestamp()
.setFooter({ text: `Outreach Event: ${event.id}` }); .setFooter({ text: `Outreach Event: ${event.id}` });
@ -263,7 +339,9 @@ export class OutreachCommand extends Subcommand {
await interaction.editReply('Event has now ended!'); await interaction.editReply('Event has now ended!');
} }
public async groupCreate(interaction: Subcommand.ChatInputCommandInteraction) { public async groupCreate(
interaction: Subcommand.ChatInputCommandInteraction,
) {
const leader = interaction.options.getUser('leader', true); const leader = interaction.options.getUser('leader', true);
const { guild } = interaction; const { guild } = interaction;
@ -277,8 +355,10 @@ export class OutreachCommand extends Subcommand {
await interaction.deferReply({ ephemeral: true }); await interaction.deferReply({ ephemeral: true });
if (await getStatFromLeader(leader.id) !== null) { if ((await getStatFromLeader(leader.id)) !== null) {
await interaction.editReply(`${leader} is already a leader for another group!`); await interaction.editReply(
`${leader} is already a leader for another group!`,
);
return; return;
} }
@ -305,7 +385,9 @@ export class OutreachCommand extends Subcommand {
await updateUser(leaderMember); await updateUser(leaderMember);
const role = await guild.roles.create({ name: `Outreach Group ${groupNo}` }); const role = await guild.roles.create({
name: `Outreach Group ${groupNo}`,
});
await createStat(event.id, leader.id, role.id); await createStat(event.id, leader.id, role.id);
@ -355,8 +437,10 @@ export class OutreachCommand extends Subcommand {
return; return;
} }
if (leader.id !== stat.stat.leaderId if (
&& !leaderMember.roles.cache.has(IDs.roles.staff.outreachCoordinator)) { leader.id !== stat.stat.leaderId &&
!leaderMember.roles.cache.has(IDs.roles.staff.outreachCoordinator)
) {
await interaction.editReply({ await interaction.editReply({
content: `You are not the leader for ${group}`, content: `You are not the leader for ${group}`,
}); });
@ -371,7 +455,7 @@ export class OutreachCommand extends Subcommand {
if (stat === null) { if (stat === null) {
await interaction.editReply({ await interaction.editReply({
content: 'You\'re not a group leader!', content: "You're not a group leader!",
}); });
return; return;
} }
@ -409,7 +493,9 @@ export class OutreachCommand extends Subcommand {
}); });
} }
public async groupUpdate(interaction: Subcommand.ChatInputCommandInteraction) { public async groupUpdate(
interaction: Subcommand.ChatInputCommandInteraction,
) {
const vegan = interaction.options.getInteger('vegan'); const vegan = interaction.options.getInteger('vegan');
const considered = interaction.options.getInteger('considered'); const considered = interaction.options.getInteger('considered');
const antiVegan = interaction.options.getInteger('anti-vegan'); const antiVegan = interaction.options.getInteger('anti-vegan');
@ -441,7 +527,7 @@ export class OutreachCommand extends Subcommand {
if (stat === null) { if (stat === null) {
await interaction.editReply({ await interaction.editReply({
content: 'You\'re not the leader of a group!', content: "You're not the leader of a group!",
}); });
return; return;
} }

View File

@ -35,12 +35,16 @@ export class BookClubCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give Book Club to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give Book Club to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -86,7 +90,9 @@ export class BookClubCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Event coordinator not found! Try again or contact a developer!'); await message.reply(
'Event coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -137,7 +143,8 @@ export class BookClubCommand extends Command {
await roleAddLog(user.id, mod.id, bookClub); await roleAddLog(user.id, mod.id, bookClub);
info.message = `Gave ${user} the ${bookClub.name} role!`; info.message = `Gave ${user} the ${bookClub.name} role!`;
await user.send(`You have been given the ${bookClub.name} role by ${mod}!`) await user
.send(`You have been given the ${bookClub.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -35,12 +35,16 @@ export class DebateHostCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give Debate Host role to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give Debate Host role to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -87,7 +91,9 @@ export class DebateHostCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Event coordinator not found! Try again or contact a developer!'); await message.reply(
'Event coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -138,7 +144,8 @@ export class DebateHostCommand extends Command {
await roleAddLog(user.id, mod.id, debateHost); await roleAddLog(user.id, mod.id, debateHost);
info.message = `Gave ${user} the ${debateHost.name} role!`; info.message = `Gave ${user} the ${debateHost.name} role!`;
await user.send(`You have been given the ${debateHost.name} role by ${mod}!`) await user
.send(`You have been given the ${debateHost.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -35,12 +35,16 @@ export class GameNightHostCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give Game Night Host role to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give Game Night Host role to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -86,7 +90,9 @@ export class GameNightHostCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Event coordinator not found! Try again or contact a developer!'); await message.reply(
'Event coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -137,7 +143,8 @@ export class GameNightHostCommand extends Command {
await roleAddLog(user.id, mod.id, gameNightHost); await roleAddLog(user.id, mod.id, gameNightHost);
info.message = `Gave ${user} the ${gameNightHost.name} role!`; info.message = `Gave ${user} the ${gameNightHost.name} role!`;
await user.send(`You have been given the ${gameNightHost.name} role by ${mod}!`) await user
.send(`You have been given the ${gameNightHost.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -35,12 +35,16 @@ export class GuestCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give Guest role to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give Guest role to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -86,7 +90,9 @@ export class GuestCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Event coordinator not found! Try again or contact a developer!'); await message.reply(
'Event coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -137,7 +143,8 @@ export class GuestCommand extends Command {
await roleAddLog(user.id, mod.id, guest); await roleAddLog(user.id, mod.id, guest);
info.message = `Gave ${user} the ${guest.name} role!`; info.message = `Gave ${user} the ${guest.name} role!`;
await user.send(`You have been given the ${guest.name} role by ${mod}!`) await user
.send(`You have been given the ${guest.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -36,12 +36,16 @@ export class MentorCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give/remove mentor role') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give/remove mentor role')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -87,7 +91,9 @@ export class MentorCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Mentor coordinator not found! Try again or contact a developer!'); await message.reply(
'Mentor coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -138,7 +144,8 @@ export class MentorCommand extends Command {
await roleAddLog(user.id, mod.id, mentor, true); await roleAddLog(user.id, mod.id, mentor, true);
info.message = `Gave ${user} the ${mentor.name} role!`; info.message = `Gave ${user} the ${mentor.name} role!`;
await user.send(`You have been given the ${mentor.name} role by ${mod}!`) await user
.send(`You have been given the ${mentor.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -35,12 +35,16 @@ export class ModCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give/remove mod role') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give/remove mod role')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -86,7 +90,9 @@ export class ModCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Mod coordinator not found! Try again or contact a developer!'); await message.reply(
'Mod coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -137,7 +143,8 @@ export class ModCommand extends Command {
await roleAddLog(user.id, mod.id, moderator, true); await roleAddLog(user.id, mod.id, moderator, true);
info.message = `Gave ${user} the ${moderator.name} role!`; info.message = `Gave ${user} the ${moderator.name} role!`;
await user.send(`You have been given the ${moderator.name} role by ${mod}!`) await user
.send(`You have been given the ${moderator.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -36,12 +36,16 @@ export class RestrictedAccessCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give/remove restricted access role') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give/remove restricted access role')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -87,7 +91,9 @@ export class RestrictedAccessCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Mod coordinator not found! Try again or contact a developer!'); await message.reply(
'Mod coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -138,7 +144,8 @@ export class RestrictedAccessCommand extends Command {
await roleAddLog(user.id, mod.id, restricted, true); await roleAddLog(user.id, mod.id, restricted, true);
info.message = `Gave ${user} the ${restricted.name} role!`; info.message = `Gave ${user} the ${restricted.name} role!`;
await user.send(`You have been given the ${restricted.name} role by ${mod}!`) await user
.send(`You have been given the ${restricted.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -35,12 +35,16 @@ export class StageHostCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give Stage Host to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give Stage Host to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -86,7 +90,9 @@ export class StageHostCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Event coordinator not found! Try again or contact a developer!'); await message.reply(
'Event coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -137,7 +143,8 @@ export class StageHostCommand extends Command {
await roleAddLog(user.id, mod.id, stageHost, true); await roleAddLog(user.id, mod.id, stageHost, true);
info.message = `Gave ${user} the ${stageHost.name} role!`; info.message = `Gave ${user} the ${stageHost.name} role!`;
await user.send(`You have been given the ${stageHost.name} role by ${mod}!`) await user
.send(`You have been given the ${stageHost.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -36,12 +36,16 @@ export class TrialModCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give/remove trial mod role') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give/remove trial mod role')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -87,7 +91,9 @@ export class TrialModCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Mod coordinator not found! Try again or contact a developer!'); await message.reply(
'Mod coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -138,7 +144,8 @@ export class TrialModCommand extends Command {
await roleAddLog(user.id, mod.id, moderator, true); await roleAddLog(user.id, mod.id, moderator, true);
info.message = `Gave ${user} the ${moderator.name} role!`; info.message = `Gave ${user} the ${moderator.name} role!`;
await user.send(`You have been given the ${moderator.name} role by ${mod}!`) await user
.send(`You have been given the ${moderator.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -35,12 +35,16 @@ export class TrialVerifierCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give/remove trial verifier role') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give/remove trial verifier role')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -86,7 +90,9 @@ export class TrialVerifierCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Verifier coordinator not found! Try again or contact a developer!'); await message.reply(
'Verifier coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -137,7 +143,8 @@ export class TrialVerifierCommand extends Command {
await roleAddLog(user.id, mod.id, trialVerifier, true); await roleAddLog(user.id, mod.id, trialVerifier, true);
info.message = `Gave ${user} the ${trialVerifier.name} role!`; info.message = `Gave ${user} the ${trialVerifier.name} role!`;
await user.send(`You have been given the ${trialVerifier.name} role by ${mod}!`) await user
.send(`You have been given the ${trialVerifier.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -35,12 +35,16 @@ export class VerifierCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give/remove verifier role') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give/remove verifier role')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -86,7 +90,9 @@ export class VerifierCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Verifier coordinator not found! Try again or contact a developer!'); await message.reply(
'Verifier coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -137,7 +143,8 @@ export class VerifierCommand extends Command {
await roleAddLog(user.id, mod.id, verifier, true); await roleAddLog(user.id, mod.id, verifier, true);
info.message = `Gave ${user} the ${verifier.name} role!`; info.message = `Gave ${user} the ${verifier.name} role!`;
await user.send(`You have been given the ${verifier.name} role by ${mod}!`) await user
.send(`You have been given the ${verifier.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -29,19 +29,25 @@ export class ActivistCommand extends Command {
name: 'activist', name: 'activist',
aliases: ['a'], aliases: ['a'],
description: 'Gives the activist role', description: 'Gives the activist role',
preconditions: [['ModCoordinatorOnly', 'VerifierCoordinatorOnly', 'VerifierOnly']], preconditions: [
['ModCoordinatorOnly', 'VerifierCoordinatorOnly', 'VerifierOnly'],
],
}); });
} }
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give activist role to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give activist role to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -121,7 +127,7 @@ export class ActivistCommand extends Command {
} }
if (modMember === undefined) { if (modMember === undefined) {
info.message = 'Error fetching the staff\'s guild member!'; info.message = "Error fetching the staff's guild member!";
return info; return info;
} }
@ -132,11 +138,14 @@ export class ActivistCommand extends Command {
// Checks if the user is Activist and to give them or remove them based on if they have it // Checks if the user is Activist and to give them or remove them based on if they have it
if (member.roles.cache.has(IDs.roles.vegan.activist)) { if (member.roles.cache.has(IDs.roles.vegan.activist)) {
if (!modMember.roles.cache.hasAny( if (
IDs.roles.staff.verifierCoordinator, !modMember.roles.cache.hasAny(
IDs.roles.staff.modCoordinator, IDs.roles.staff.verifierCoordinator,
)) { IDs.roles.staff.modCoordinator,
info.message = 'You need to be a verifier coordinator to remove this role!'; )
) {
info.message =
'You need to be a verifier coordinator to remove this role!';
return info; return info;
} }
@ -153,15 +162,17 @@ export class ActivistCommand extends Command {
await roleAddLog(user.id, mod.id, activist); await roleAddLog(user.id, mod.id, activist);
info.message = `Gave ${user} the ${activist.name} role!`; info.message = `Gave ${user} the ${activist.name} role!`;
await user.send( await user
`${user} you have been given the ${activist.name} role by ${mod}! ` .send(
+ `This means that if you'd wish to engage with non-vegans in <#${IDs.channels.nonVegan.general}>, you should follow these rules:\n\n` `${user} you have been given the ${activist.name} role by ${mod}! ` +
+ '1. Try to move conversations with non-vegans towards veganism/animal ethics\n' `This means that if you'd wish to engage with non-vegans in <#${IDs.channels.nonVegan.general}>, you should follow these rules:\n\n` +
+ '2. Don\'t discuss social topics while activism is happening\n' '1. Try to move conversations with non-vegans towards veganism/animal ethics\n' +
+ '3. Have evidence for claims you make. "I don\'t know" is an acceptable answer. Chances are someone here knows or you can take time to find out\n' "2. Don't discuss social topics while activism is happening\n" +
+ '4. Don\'t advocate for baby steps towards veganism. Participation in exploitation can stop today\n' '3. Have evidence for claims you make. "I don\'t know" is an acceptable answer. Chances are someone here knows or you can take time to find out\n' +
+ '5. Differences in opinion between activists should be resolved in vegan spaces, not in the chat with non-vegans', "4. Don't advocate for baby steps towards veganism. Participation in exploitation can stop today\n" +
).catch(() => {}); '5. Differences in opinion between activists should be resolved in vegan spaces, not in the chat with non-vegans',
)
.catch(() => {});
info.success = true; info.success = true;
return info; return info;
} }

View File

@ -28,19 +28,25 @@ export class ARAVeganCommand extends Command {
...options, ...options,
name: 'aravegan', name: 'aravegan',
description: 'Gives the ara vegan role', description: 'Gives the ara vegan role',
preconditions: [['ModCoordinatorOnly', 'VerifierCoordinatorOnly', 'VerifierOnly']], preconditions: [
['ModCoordinatorOnly', 'VerifierCoordinatorOnly', 'VerifierOnly'],
],
}); });
} }
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give vegan role to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give vegan role to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -120,7 +126,7 @@ export class ARAVeganCommand extends Command {
} }
if (modMember === undefined) { if (modMember === undefined) {
info.message = 'Error fetching the staff\'s guild member!'; info.message = "Error fetching the staff's guild member!";
return info; return info;
} }
@ -131,11 +137,14 @@ export class ARAVeganCommand extends Command {
// Checks if the user is an ARA Vegan and to give them or remove them based on if they have it // Checks if the user is an ARA Vegan and to give them or remove them based on if they have it
if (member.roles.cache.has(IDs.roles.vegan.araVegan)) { if (member.roles.cache.has(IDs.roles.vegan.araVegan)) {
if (!modMember.roles.cache.hasAny( if (
IDs.roles.staff.verifierCoordinator, !modMember.roles.cache.hasAny(
IDs.roles.staff.modCoordinator, IDs.roles.staff.verifierCoordinator,
)) { IDs.roles.staff.modCoordinator,
info.message = 'You need to be a verifier coordinator to remove these roles!'; )
) {
info.message =
'You need to be a verifier coordinator to remove these roles!';
return info; return info;
} }
@ -158,7 +167,8 @@ export class ARAVeganCommand extends Command {
await roleAddLog(user.id, mod.id, vegan); await roleAddLog(user.id, mod.id, vegan);
info.message = `Gave ${user} the ${vegan.name} role!`; info.message = `Gave ${user} the ${vegan.name} role!`;
await user.send(`You have been given the ${vegan.name} role by ${mod}!`) await user
.send(`You have been given the ${vegan.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -36,12 +36,16 @@ export class ConvincedCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give convinced to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give convinced to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -143,10 +147,13 @@ export class ConvincedCommand extends Command {
await roleAddLog(user.id, mod.id, convinced); await roleAddLog(user.id, mod.id, convinced);
info.message = `Gave ${user} the ${convinced.name} role!`; info.message = `Gave ${user} the ${convinced.name} role!`;
await user.send(`You have been given the ${convinced.name} role by ${mod}!` await user
+ '\n\nThis role allows you to get access to the Diet Support section in this server that can help you go vegan ' .send(
+ 'and other parts of the server! :)' `You have been given the ${convinced.name} role by ${mod}!` +
+ '\n\nThank you for caring about the animals 💚') '\n\nThis role allows you to get access to the Diet Support section in this server that can help you go vegan ' +
'and other parts of the server! :)' +
'\n\nThank you for caring about the animals 💚',
)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;

View File

@ -36,12 +36,16 @@ export class PlusCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give/remove plus to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give/remove plus to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -86,7 +90,9 @@ export class PlusCommand extends Command {
if (mod === null) { if (mod === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Coordinator not found! Try again or contact a developer!'); await message.reply(
'Coordinator not found! Try again or contact a developer!',
);
return; return;
} }
@ -137,7 +143,8 @@ export class PlusCommand extends Command {
await roleAddLog(user.id, mod.id, plus); await roleAddLog(user.id, mod.id, plus);
info.message = `Gave ${user} the ${plus.name} role!`; info.message = `Gave ${user} the ${plus.name} role!`;
await user.send(`You have been given the ${plus.name} role by ${mod}!`) await user
.send(`You have been given the ${plus.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -36,12 +36,16 @@ export class TrustedCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give/remove trusted to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give/remove trusted to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -138,10 +142,13 @@ export class TrustedCommand extends Command {
await roleAddLog(user.id, mod.id, trusted); await roleAddLog(user.id, mod.id, trusted);
info.message = `Gave ${user} the ${trusted.name} role!`; info.message = `Gave ${user} the ${trusted.name} role!`;
await user.send(`You have been given the ${trusted.name} role by ${mod}!` await user
+ '\n\nThis role allows you to post attachments to the server and stream in VCs.' .send(
+ '\nMake sure that you follow the rules, and don\'t post anything NSFW, anything objectifying animals and follow Discord\'s ToS.' `You have been given the ${trusted.name} role by ${mod}!` +
+ `\nNot following these rules can result in the removal of the ${trusted.name} role.`) '\n\nThis role allows you to post attachments to the server and stream in VCs.' +
"\nMake sure that you follow the rules, and don't post anything NSFW, anything objectifying animals and follow Discord's ToS." +
`\nNot following these rules can result in the removal of the ${trusted.name} role.`,
)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -29,19 +29,25 @@ export class VeganCommand extends Command {
name: 'vegan', name: 'vegan',
aliases: ['v'], aliases: ['v'],
description: 'Gives the vegan role', description: 'Gives the vegan role',
preconditions: [['ModCoordinatorOnly', 'VerifierCoordinatorOnly', 'VerifierOnly']], preconditions: [
['ModCoordinatorOnly', 'VerifierCoordinatorOnly', 'VerifierOnly'],
],
}); });
} }
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give vegan role to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give vegan role to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -121,7 +127,7 @@ export class VeganCommand extends Command {
} }
if (modMember === undefined) { if (modMember === undefined) {
info.message = 'Error fetching the staff\'s guild member!'; info.message = "Error fetching the staff's guild member!";
return info; return info;
} }
@ -132,11 +138,14 @@ export class VeganCommand extends Command {
// Checks if the user is Vegan and to give them or remove them based on if they have it // Checks if the user is Vegan and to give them or remove them based on if they have it
if (member.roles.cache.has(IDs.roles.vegan.vegan)) { if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
if (!modMember.roles.cache.hasAny( if (
IDs.roles.staff.verifierCoordinator, !modMember.roles.cache.hasAny(
IDs.roles.staff.modCoordinator, IDs.roles.staff.verifierCoordinator,
)) { IDs.roles.staff.modCoordinator,
info.message = 'You need to be a verifier coordinator to remove these roles!'; )
) {
info.message =
'You need to be a verifier coordinator to remove these roles!';
return info; return info;
} }
@ -154,8 +163,7 @@ export class VeganCommand extends Command {
} }
// Add Vegan role to the user // Add Vegan role to the user
await member.roles.add([vegan, await member.roles.add([vegan, IDs.roles.vegan.nvAccess]);
IDs.roles.vegan.nvAccess]);
await member.roles.remove([ await member.roles.remove([
IDs.roles.nonvegan.nonvegan, IDs.roles.nonvegan.nonvegan,
IDs.roles.nonvegan.convinced, IDs.roles.nonvegan.convinced,
@ -164,7 +172,8 @@ export class VeganCommand extends Command {
await roleAddLog(user.id, mod.id, vegan); await roleAddLog(user.id, mod.id, vegan);
info.message = `Gave ${user} the ${vegan.name} role!`; info.message = `Gave ${user} the ${vegan.name} role!`;
await user.send(`You have been given the ${vegan.name} role by ${mod}!`) await user
.send(`You have been given the ${vegan.name} role by ${mod}!`)
.catch(() => {}); .catch(() => {});
info.success = true; info.success = true;
return info; return info;

View File

@ -36,12 +36,16 @@ export class VegCuriousCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give veg curious to') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to give veg curious to')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -121,7 +125,7 @@ export class VegCuriousCommand extends Command {
} }
if (modMember === undefined) { if (modMember === undefined) {
info.message = 'Error fetching the staff\'s guild member!'; info.message = "Error fetching the staff's guild member!";
return info; return info;
} }
@ -134,13 +138,15 @@ export class VegCuriousCommand extends Command {
if (!modMember.roles.cache.has(IDs.roles.staff.mentorCoordinator)) { if (!modMember.roles.cache.has(IDs.roles.staff.mentorCoordinator)) {
// Only Mentor Coordinators can remove Veg Curious role // Only Mentor Coordinators can remove Veg Curious role
if (member.roles.cache.has(IDs.roles.nonvegan.vegCurious)) { if (member.roles.cache.has(IDs.roles.nonvegan.vegCurious)) {
info.message = 'You need to be a mentor coordinator to remove this role!'; info.message =
'You need to be a mentor coordinator to remove this role!';
return info; return info;
} }
// Only Mentor Coordinators can give vegans Veg Curious role // Only Mentor Coordinators can give vegans Veg Curious role
if (member.roles.cache.has(IDs.roles.vegan.vegan)) { if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
info.message = 'You need to be a mentor coordinator to give vegans this role!'; info.message =
'You need to be a mentor coordinator to give vegans this role!';
return info; return info;
} }
} }
@ -160,8 +166,12 @@ export class VegCuriousCommand extends Command {
await roleAddLog(user.id, mod.id, vegCurious); await roleAddLog(user.id, mod.id, vegCurious);
info.message = `Gave ${user} the ${vegCurious.name} role!`; info.message = `Gave ${user} the ${vegCurious.name} role!`;
await user.send(`You have been given the ${vegCurious.name} role by ${mod} ` await user
+ 'which gives you access to the diet support section').catch(() => {}); .send(
`You have been given the ${vegCurious.name} role by ${mod} ` +
'which gives you access to the diet support section',
)
.catch(() => {});
info.success = true; info.success = true;
return info; return info;
} }

View File

@ -29,15 +29,14 @@ export class ApplyCommand extends Command {
}); });
} }
message = 'If you want to help out in ARA and support animals at the same time, ' message =
+ 'apply here: https://forms.gle/kgBHbB7LHFUJXhui6 and we\'ll try to get back as soon as possible!'; 'If you want to help out in ARA and support animals at the same time, ' +
"apply here: https://forms.gle/kgBHbB7LHFUJXhui6 and we'll try to get back as soon as possible!";
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) => builder.setName(this.name).setDescription(this.description),
.setName(this.name)
.setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },

View File

@ -33,9 +33,7 @@ export class RenameUserCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) => builder.setName(this.name).setDescription(this.description),
.setName(this.name)
.setDescription(this.description),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -70,8 +68,9 @@ export class RenameUserCommand extends Command {
} }
await interaction.reply({ await interaction.reply({
content: `${vegan.name}s: \`${vegan.members.size}\`` content:
+ `\n${notVegan.name}s: \`${notVegan.members.size}\``, `${vegan.name}s: \`${vegan.members.size}\`` +
`\n${notVegan.name}s: \`${notVegan.members.size}\``,
fetchReply: true, fetchReply: true,
}); });
} }
@ -81,7 +80,9 @@ export class RenameUserCommand extends Command {
if (guild === null) { if (guild === null) {
await message.react('❌'); await message.react('❌');
await message.reply('Guild not found, please try again or contact a developer!'); await message.reply(
'Guild not found, please try again or contact a developer!',
);
return; return;
} }
@ -99,8 +100,9 @@ export class RenameUserCommand extends Command {
} }
await message.reply({ await message.reply({
content: `${vegan.name}s: \`${vegan.members.size}\`` content:
+ `\n${notVegan.name}s: \`${notVegan.members.size}\``, `${vegan.name}s: \`${vegan.members.size}\`` +
`\n${notVegan.name}s: \`${notVegan.members.size}\``,
}); });
await message.react('✅'); await message.react('✅');

View File

@ -29,14 +29,16 @@ export class HelpCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => builder registry.registerChatInputCommand((builder) =>
.setName(this.name) builder.setName(this.name).setDescription(this.description),
.setDescription(this.description)); );
} }
embed = new EmbedBuilder() embed = new EmbedBuilder()
.setColor(0x0099FF) .setColor(0x0099ff)
.setDescription('For a list of all the commands, click [here](https://github.com/veganhacktivists/arabot/blob/main/docs/COMMANDS.md)'); .setDescription(
'For a list of all the commands, click [here](https://github.com/veganhacktivists/arabot/blob/main/docs/COMMANDS.md)',
);
// Command run // Command run
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) { public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {

View File

@ -31,20 +31,29 @@ export class InfoCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addStringOption((option) => option.setName('info') .setDescription(this.description)
.setDescription('Information you want') .addStringOption((option) =>
.setRequired(true) option
.addChoices( .setName('info')
{ name: 'Trusted', value: 'trusted' }, .setDescription('Information you want')
{ name: 'Veg Curious', value: 'vegCurious' }, .setRequired(true)
{ name: 'Verification', value: 'verification' }, .addChoices(
{ name: 'ModMail', value: 'modMail' }, { name: 'Trusted', value: 'trusted' },
)) { name: 'Veg Curious', value: 'vegCurious' },
.addBooleanOption((option) => option.setName('visible') { name: 'Verification', value: 'verification' },
.setDescription('If you want this this information visible to everyone')), { name: 'ModMail', value: 'modMail' },
),
)
.addBooleanOption((option) =>
option
.setName('visible')
.setDescription(
'If you want this this information visible to everyone',
),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -66,34 +75,39 @@ export class InfoCommand extends Command {
switch (option) { switch (option) {
case 'trusted': case 'trusted':
message = 'The trusted role (✅) gives you permissions to send images and share your screen and use the ' message =
+ 'camera (unless you\'re a minor) on voice chats.\n\n' 'The trusted role (✅) gives you permissions to send images and share your screen and use the ' +
+ 'If you want the trusted role, please contact a moderator the moderators will determine whether ' "camera (unless you're a minor) on voice chats.\n\n" +
+ 'you can have the role. This depends on your behaviour on the server.'; 'If you want the trusted role, please contact a moderator the moderators will determine whether ' +
'you can have the role. This depends on your behaviour on the server.';
break; break;
case 'vegCurious': case 'vegCurious':
message = 'Would you like the Veg Curious role? It will allow you access to our diet support section where our ' message =
+ 'mentors can assist you. Mentors can provide product or substitution suggestions as well as other advice. ' 'Would you like the Veg Curious role? It will allow you access to our diet support section where our ' +
+ 'They also host a stage that highlights new recipes weekly, which you will get pinged for.\n\n' 'mentors can assist you. Mentors can provide product or substitution suggestions as well as other advice. ' +
+ 'If you\'re interested in the role, ask a member of staff or DM ModMail for the role. This role is ' 'They also host a stage that highlights new recipes weekly, which you will get pinged for.\n\n' +
+ 'available for non-vegans and vegans that are genuinely interested in learning more about plant-based ' "If you're interested in the role, ask a member of staff or DM ModMail for the role. This role is " +
+ 'diets!'; 'available for non-vegans and vegans that are genuinely interested in learning more about plant-based ' +
'diets!';
break; break;
case 'verification': case 'verification':
message = 'If you want to have the vegan or activist role, you\'ll need to do a voice verification. ' message =
+ 'To do this, hop into the \'Verification\' voice channel.' "If you want to have the vegan or activist role, you'll need to do a voice verification. " +
+ '\n\nIf there aren\'t any verifiers available, you\'ll be disconnected, and you can rejoin later.'; "To do this, hop into the 'Verification' voice channel." +
"\n\nIf there aren't any verifiers available, you'll be disconnected, and you can rejoin later.";
break; break;
case 'modMail': case 'modMail':
message = 'If you would like to contact the Moderators privately, the best way to do so would be to send a ' message =
+ 'ModMail.\n\n' 'If you would like to contact the Moderators privately, the best way to do so would be to send a ' +
+ 'To do so, you will have to DM <@575252669443211264> then send it a message and it will prompt you to ' 'ModMail.\n\n' +
+ 'set up ModMail. Once you have set up ModMail, you can send a message and you will have to select this ' 'To do so, you will have to DM <@575252669443211264> then send it a message and it will prompt you to ' +
+ 'server to send it to. You will get a message from ModMail saying \'Message Sent\' when we have received ' 'set up ModMail. Once you have set up ModMail, you can send a message and you will have to select this ' +
+ 'your message!'; "server to send it to. You will get a message from ModMail saying 'Message Sent' when we have received " +
'your message!';
break; break;
default: default:
message = 'You\'re not supposed to find this, here\'s a virtual vegan cookie! :D'; message =
"You're not supposed to find this, here's a virtual vegan cookie! :D";
} }
await interaction.reply({ await interaction.reply({

View File

@ -32,19 +32,25 @@ export class PingCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => builder registry.registerChatInputCommand((builder) =>
.setName(this.name) builder.setName(this.name).setDescription(this.description),
.setDescription(this.description)); );
} }
// Command run // Command run
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) { public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
const msg = await interaction.reply({ content: 'Ping?', ephemeral: true, fetchReply: true }); const msg = await interaction.reply({
content: 'Ping?',
ephemeral: true,
fetchReply: true,
});
if (isMessageInstance(msg)) { if (isMessageInstance(msg)) {
const diff = msg.createdTimestamp - interaction.createdTimestamp; const diff = msg.createdTimestamp - interaction.createdTimestamp;
const ping = Math.round(this.container.client.ws.ping); const ping = Math.round(this.container.client.ws.ping);
return interaction.editReply(`Pong 🏓! (Round trip took: ${diff}ms. Heartbeat: ${ping}ms.)`); return interaction.editReply(
`Pong 🏓! (Round trip took: ${diff}ms. Heartbeat: ${ping}ms.)`,
);
} }
return interaction.editReply('Failed to retrieve ping :('); return interaction.editReply('Failed to retrieve ping :(');
@ -56,6 +62,8 @@ export class PingCommand extends Command {
const diff = msg.createdTimestamp - message.createdTimestamp; const diff = msg.createdTimestamp - message.createdTimestamp;
const ping = Math.round(this.container.client.ws.ping); const ping = Math.round(this.container.client.ws.ping);
return msg.edit(`Pong 🏓! (Round trip took: ${diff}ms. Heartbeat: ${ping}ms.)`); return msg.edit(
`Pong 🏓! (Round trip took: ${diff}ms. Heartbeat: ${ping}ms.)`,
);
} }
} }

View File

@ -18,14 +18,12 @@
*/ */
import { Args, Command, RegisterBehavior } from '@sapphire/framework'; import { Args, Command, RegisterBehavior } from '@sapphire/framework';
import type { import type { Message, User, Guild, Snowflake } from 'discord.js';
Message,
User,
Guild,
Snowflake,
} from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
import { finishVerifyMessages, giveVerificationRoles } from '#utils/verification'; import {
finishVerifyMessages,
giveVerificationRoles,
} from '#utils/verification';
import { manualVerification } from '#utils/database/verification'; import { manualVerification } from '#utils/database/verification';
export class VerifyCommand extends Command { export class VerifyCommand extends Command {
@ -35,22 +33,31 @@ export class VerifyCommand extends Command {
name: 'verify', name: 'verify',
aliases: ['ver'], aliases: ['ver'],
description: 'Gives roles to the user', description: 'Gives roles to the user',
preconditions: [['ModCoordinatorOnly', 'VerifierCoordinatorOnly', 'VerifierOnly']], preconditions: [
['ModCoordinatorOnly', 'VerifierCoordinatorOnly', 'VerifierOnly'],
],
}); });
} }
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to give the roles to') .addUserOption((option) =>
.setRequired(true)) option
.addStringOption((option) => option.setName('roles') .setName('user')
.setDescription('Roles to give to the user') .setDescription('User to give the roles to')
.setRequired(true)), .setRequired(true),
)
.addStringOption((option) =>
option
.setName('roles')
.setDescription('Roles to give to the user')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -76,7 +83,13 @@ export class VerifyCommand extends Command {
return; return;
} }
const verify = await this.verify(user, verifier.id, roles, messageId, guild); const verify = await this.verify(
user,
verifier.id,
roles,
messageId,
guild,
);
await interaction.reply({ await interaction.reply({
content: verify.message, content: verify.message,
@ -113,7 +126,13 @@ export class VerifyCommand extends Command {
return; return;
} }
const verify = await this.verify(user, verifier.id, roles, message.id, guild); const verify = await this.verify(
user,
verifier.id,
roles,
message.id,
guild,
);
await message.reply(verify.message); await message.reply(verify.message);
await message.react(verify.success ? '✅' : '❌'); await message.react(verify.success ? '✅' : '❌');
@ -144,8 +163,7 @@ export class VerifyCommand extends Command {
// Checks if member is null // Checks if member is null
if (member === undefined) { if (member === undefined) {
member = await guild.members.fetch(user.id) member = await guild.members.fetch(user.id).catch(() => undefined);
.catch(() => undefined);
if (member === undefined) { if (member === undefined) {
info.message = 'Failed to fetch member'; info.message = 'Failed to fetch member';
return info; return info;
@ -153,7 +171,7 @@ export class VerifyCommand extends Command {
} }
if (member.roles.cache.hasAny(...IDs.roles.restrictions.restricted)) { if (member.roles.cache.hasAny(...IDs.roles.restrictions.restricted)) {
info.message = 'Can\'t verify a restricted user!'; info.message = "Can't verify a restricted user!";
return info; return info;
} }
@ -161,8 +179,7 @@ export class VerifyCommand extends Command {
// Checks if verifier is null // Checks if verifier is null
if (verifier === undefined) { if (verifier === undefined) {
verifier = await guild.members.fetch(user.id) verifier = await guild.members.fetch(user.id).catch(() => undefined);
.catch(() => undefined);
if (verifier === undefined) { if (verifier === undefined) {
info.message = 'Failed to fetch verifier'; info.message = 'Failed to fetch verifier';
return info; return info;
@ -203,15 +220,19 @@ export class VerifyCommand extends Command {
return info; return info;
} }
if ((roles.vegan || member.roles.cache.has(IDs.roles.vegan.vegan)) if (
&& (roleArgs.includes('nv') || roles.vegCurious || roles.convinced)) { (roles.vegan || member.roles.cache.has(IDs.roles.vegan.vegan)) &&
info.message = 'Can\'t give non-vegan roles to a vegan'; (roleArgs.includes('nv') || roles.vegCurious || roles.convinced)
) {
info.message = "Can't give non-vegan roles to a vegan";
return info; return info;
} }
if (roleArgs.includes('nv') if (
&& (roles.vegan || roles.activist || roles.araVegan)) { roleArgs.includes('nv') &&
info.message = 'Can\'t give vegan roles to a non-vegan'; (roles.vegan || roles.activist || roles.araVegan)
) {
info.message = "Can't give vegan roles to a non-vegan";
return info; return info;
} }
@ -221,8 +242,10 @@ export class VerifyCommand extends Command {
await manualVerification(messageId, member, verifier, roles); await manualVerification(messageId, member, verifier, roles);
if (member.roles.cache.has(IDs.roles.nonvegan.nonvegan) if (
&& (roles.vegan || roles.activist || roles.araVegan)) { member.roles.cache.has(IDs.roles.nonvegan.nonvegan) &&
(roles.vegan || roles.activist || roles.araVegan)
) {
await member.roles.remove([ await member.roles.remove([
IDs.roles.nonvegan.nonvegan, IDs.roles.nonvegan.nonvegan,
IDs.roles.nonvegan.vegCurious, IDs.roles.nonvegan.vegCurious,

View File

@ -34,12 +34,16 @@ export class VerifyTimeoutRemoveCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to remove timeout from') .addUserOption((option) =>
.setRequired(true)), option
.setName('user')
.setDescription('User to remove timeout from')
.setRequired(true),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -67,8 +71,7 @@ export class VerifyTimeoutRemoveCommand extends Command {
let member = guild.members.cache.get(user.id); let member = guild.members.cache.get(user.id);
if (member === undefined) { if (member === undefined) {
member = await guild.members.fetch(user.id) member = await guild.members.fetch(user.id).catch(undefined);
.catch(undefined);
if (member === undefined) { if (member === undefined) {
await interaction.editReply(`${user} is not on this server!`); await interaction.editReply(`${user} is not on this server!`);
return; return;
@ -81,7 +84,9 @@ export class VerifyTimeoutRemoveCommand extends Command {
} }
if (await checkVerificationFinish(user.id)) { if (await checkVerificationFinish(user.id)) {
await interaction.editReply(`Can't remove ${user}'s role as they failed their last verification`); await interaction.editReply(
`Can't remove ${user}'s role as they failed their last verification`,
);
return; return;
} }

View File

@ -34,11 +34,13 @@ export class RankCommand extends Command {
// Registers that this is a slash command // Registers that this is a slash command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand( registry.registerChatInputCommand(
(builder) => builder (builder) =>
.setName(this.name) builder
.setDescription(this.description) .setName(this.name)
.addUserOption((option) => option.setName('user') .setDescription(this.description)
.setDescription('User to show rank for')), .addUserOption((option) =>
option.setName('user').setDescription('User to show rank for'),
),
{ {
behaviorWhenNotIdentical: RegisterBehavior.Overwrite, behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
}, },
@ -109,8 +111,7 @@ export class RankCommand extends Command {
let member = guild.members.cache.get(user.id); let member = guild.members.cache.get(user.id);
if (member === undefined) { if (member === undefined) {
member = await guild.members.fetch(user.id) member = await guild.members.fetch(user.id).catch(() => undefined);
.catch(() => undefined);
if (member === undefined) { if (member === undefined) {
info.message = 'The user is not on this server!'; info.message = 'The user is not on this server!';
return info; return info;
@ -123,10 +124,17 @@ export class RankCommand extends Command {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor('#00ff7d') .setColor('#00ff7d')
.setAuthor({ name: `${member.displayName}'s Rank`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
name: `${member.displayName}'s Rank`,
iconURL: `${user.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'Rank', value: `${rank.rank}` }, { name: 'Rank', value: `${rank.rank}` },
{ name: 'Level', value: `${rank.level} (${rank.xpNextLevel}/${xpNextLevel} XP)`, inline: true }, {
name: 'Level',
value: `${rank.level} (${rank.xpNextLevel}/${xpNextLevel} XP)`,
inline: true,
},
{ name: 'Total XP', value: `${rank.xp}`, inline: true }, { name: 'Total XP', value: `${rank.xp}`, inline: true },
{ name: 'Total messages', value: `${rank.messages}` }, { name: 'Total messages', value: `${rank.messages}` },
); );

View File

@ -17,7 +17,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { InteractionHandler, InteractionHandlerTypes } from '@sapphire/framework'; import {
InteractionHandler,
InteractionHandlerTypes,
} from '@sapphire/framework';
import type { PieceContext } from '@sapphire/framework'; import type { PieceContext } from '@sapphire/framework';
import type { ButtonInteraction, GuildMember } from 'discord.js'; import type { ButtonInteraction, GuildMember } from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
@ -39,8 +42,9 @@ export class NonVeganAccessButtonHandler extends InteractionHandler {
public async run(interaction: ButtonInteraction) { public async run(interaction: ButtonInteraction) {
let { member } = interaction; let { member } = interaction;
const errorMessage = 'There was an error giving you the role, please try again later or contact ModMail/the developer ' const errorMessage =
+ 'to sort out this problem.'; 'There was an error giving you the role, please try again later or contact ModMail/the developer ' +
'to sort out this problem.';
if (member === null) { if (member === null) {
await interaction.reply({ await interaction.reply({
@ -64,8 +68,9 @@ export class NonVeganAccessButtonHandler extends InteractionHandler {
if (member.roles.cache.has(IDs.roles.vegan.nvAccess)) { if (member.roles.cache.has(IDs.roles.vegan.nvAccess)) {
await member.roles.remove(IDs.roles.vegan.nvAccess); await member.roles.remove(IDs.roles.vegan.nvAccess);
await interaction.reply({ await interaction.reply({
content: 'Your access from the non vegan section has been removed. ' content:
+ 'If you want to gain access again, click this button again.', 'Your access from the non vegan section has been removed. ' +
'If you want to gain access again, click this button again.',
ephemeral: true, ephemeral: true,
}); });
return; return;
@ -73,8 +78,9 @@ export class NonVeganAccessButtonHandler extends InteractionHandler {
await member.roles.add(IDs.roles.vegan.nvAccess); await member.roles.add(IDs.roles.vegan.nvAccess);
await interaction.reply({ await interaction.reply({
content: 'Your access to the non vegan section has been given back. ' content:
+ 'If you want to remove access again, click this button again.', 'Your access to the non vegan section has been given back. ' +
'If you want to remove access again, click this button again.',
ephemeral: true, ephemeral: true,
}); });
} catch (error) { } catch (error) {

View File

@ -17,7 +17,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { InteractionHandler, InteractionHandlerTypes } from '@sapphire/framework'; import {
InteractionHandler,
InteractionHandlerTypes,
} from '@sapphire/framework';
import type { PieceContext } from '@sapphire/framework'; import type { PieceContext } from '@sapphire/framework';
import type { ButtonInteraction, GuildMember, TextChannel } from 'discord.js'; import type { ButtonInteraction, GuildMember, TextChannel } from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
@ -38,15 +41,17 @@ export class WelcomeButtonHandler extends InteractionHandler {
public async run(interaction: ButtonInteraction) { public async run(interaction: ButtonInteraction) {
let { member } = interaction; let { member } = interaction;
const general = this.container.client.channels.cache const general = this.container.client.channels.cache.get(
.get(IDs.channels.nonVegan.general) as TextChannel | undefined; IDs.channels.nonVegan.general,
) as TextChannel | undefined;
if (general === undefined) { if (general === undefined) {
return; return;
} }
if (member === null) { if (member === null) {
await interaction.reply({ await interaction.reply({
content: 'There was an error giving you the role, please try again later or contact ModMail to be let into this server.', content:
'There was an error giving you the role, please try again later or contact ModMail to be let into this server.',
ephemeral: true, ephemeral: true,
}); });
return; return;
@ -59,19 +64,23 @@ export class WelcomeButtonHandler extends InteractionHandler {
if (!member.voice.channel) { if (!member.voice.channel) {
await member.roles.add(IDs.roles.nonvegan.nonvegan); await member.roles.add(IDs.roles.nonvegan.nonvegan);
await general.send(`${member} Welcome to ARA! :D Please check <#${IDs.channels.information.roles}> ` await general.send(
+ `and remember to follow the <#${IDs.channels.information.conduct}> and to respect ongoing discussion and debates.` `${member} Welcome to ARA! :D Please check <#${IDs.channels.information.roles}> ` +
+ '\n\nIf you would like to be verified as a vegan, join the \'Verification\' voice channel.'); `and remember to follow the <#${IDs.channels.information.conduct}> and to respect ongoing discussion and debates.` +
"\n\nIf you would like to be verified as a vegan, join the 'Verification' voice channel.",
);
return; return;
} }
await interaction.reply({ await interaction.reply({
content: 'You\'re currently in a verification, you\'ll have to leave the verification or get verified before being able to access the server again.', content:
"You're currently in a verification, you'll have to leave the verification or get verified before being able to access the server again.",
ephemeral: true, ephemeral: true,
}); });
} catch (error) { } catch (error) {
await interaction.reply({ await interaction.reply({
content: 'There was an error giving you the role, please try again later or contact ModMail to be let into this server.', content:
'There was an error giving you the role, please try again later or contact ModMail to be let into this server.',
ephemeral: true, ephemeral: true,
}); });
} }

View File

@ -69,7 +69,9 @@ export class BanListener extends Listener {
// Check if the bot banned the user // Check if the bot banned the user
if (executor.id === this.container.client.user.id) { if (executor.id === this.container.client.user.id) {
this.container.logger.error('BanListener: got past the checkActive and bot banned this user.'); this.container.logger.error(
'BanListener: got past the checkActive and bot banned this user.',
);
return; return;
} }
@ -81,10 +83,11 @@ export class BanListener extends Listener {
// Checks if GuildMember is null // Checks if GuildMember is null
if (mod === undefined) { if (mod === undefined) {
mod = await guild.members.fetch(executor.id) mod = await guild.members.fetch(executor.id).catch(() => undefined);
.catch(() => undefined);
if (mod === undefined) { if (mod === undefined) {
this.container.logger.error('UnbanListener: Could not fetch moderator.'); this.container.logger.error(
'UnbanListener: Could not fetch moderator.',
);
return; return;
} }
} }
@ -93,7 +96,9 @@ export class BanListener extends Listener {
await addExistingUser(mod); await addExistingUser(mod);
if (await checkBan(user.id)) { if (await checkBan(user.id)) {
this.container.logger.error('BanListener: got past the checkActive at the start.'); this.container.logger.error(
'BanListener: got past the checkActive at the start.',
);
return; return;
} }
@ -110,12 +115,14 @@ export class BanListener extends Listener {
await addBan(user.id, mod.id, `${reason}`); await addBan(user.id, mod.id, `${reason}`);
// Log the ban // Log the ban
let logChannel = guild.channels.cache let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
.get(IDs.channels.logs.restricted) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
logChannel = await guild.channels logChannel = (await guild.channels.fetch(
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined; IDs.channels.logs.restricted,
)) as TextChannel | undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
this.container.logger.error('BanListener: Could not fetch log channel'); this.container.logger.error('BanListener: Could not fetch log channel');
return; return;
@ -124,7 +131,10 @@ export class BanListener extends Listener {
const log = new EmbedBuilder() const log = new EmbedBuilder()
.setColor('#FF0000') .setColor('#FF0000')
.setAuthor({ name: `Banned ${user.tag} (not done via bot)`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
name: `Banned ${user.tag} (not done via bot)`,
iconURL: `${user.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'User', value: `${user}`, inline: true }, { name: 'User', value: `${user}`, inline: true },
{ name: 'Moderator', value: `${mod}`, inline: true }, { name: 'Moderator', value: `${mod}`, inline: true },

View File

@ -32,8 +32,7 @@ export class BanJoinListener extends Listener {
public async run(user: GuildMember) { public async run(user: GuildMember) {
// Check if the user is banned // Check if the user is banned
if (!await checkBan(user.id) if (!(await checkBan(user.id)) && !(await checkTempBan(user.id))) {
&& !await checkTempBan(user.id)) {
return; return;
} }
@ -41,8 +40,11 @@ export class BanJoinListener extends Listener {
const reason = await getBanReason(user.id); const reason = await getBanReason(user.id);
// Send DM for ban reason // Send DM for ban reason
await user.send(`You have been banned from ARA for: ${reason}` await user
+ '\n\nhttps://vbcamp.org/ARA') .send(
`You have been banned from ARA for: ${reason}` +
'\n\nhttps://vbcamp.org/ARA',
)
.catch(() => {}); .catch(() => {});
// Ban the user // Ban the user

View File

@ -72,10 +72,11 @@ export class UnbanListener extends Listener {
// Checks if GuildMember is null // Checks if GuildMember is null
if (mod === undefined) { if (mod === undefined) {
mod = await guild.members.fetch(executor.id) mod = await guild.members.fetch(executor.id).catch(() => undefined);
.catch(() => undefined);
if (mod === undefined) { if (mod === undefined) {
this.container.logger.error('UnbanListener: Could not fetch moderator.'); this.container.logger.error(
'UnbanListener: Could not fetch moderator.',
);
return; return;
} }
} }
@ -84,7 +85,7 @@ export class UnbanListener extends Listener {
await addExistingUser(mod); await addExistingUser(mod);
// Check for missing ban on database // Check for missing ban on database
if (!await checkBan(user.id)) { if (!(await checkBan(user.id))) {
// Check if user and mod are on the database // Check if user and mod are on the database
await addEmptyUser(user.id); await addEmptyUser(user.id);
@ -96,21 +97,28 @@ export class UnbanListener extends Listener {
await removeBan(user.id, mod.id); await removeBan(user.id, mod.id);
// Log the ban // Log the ban
let logChannel = guild.channels.cache let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
.get(IDs.channels.logs.restricted) as TextChannel | undefined; | TextChannel
| undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
logChannel = await guild.channels logChannel = (await guild.channels.fetch(
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined; IDs.channels.logs.restricted,
)) as TextChannel | undefined;
if (logChannel === undefined) { if (logChannel === undefined) {
this.container.logger.error('UnbanListener: Could not fetch log channel'); this.container.logger.error(
'UnbanListener: Could not fetch log channel',
);
return; return;
} }
} }
const log = new EmbedBuilder() const log = new EmbedBuilder()
.setColor('#28A745') .setColor('#28A745')
.setAuthor({ name: `Unbanned ${user.tag} (not done via bot)`, iconURL: `${user.displayAvatarURL()}` }) .setAuthor({
name: `Unbanned ${user.tag} (not done via bot)`,
iconURL: `${user.displayAvatarURL()}`,
})
.addFields( .addFields(
{ name: 'User', value: `${user}`, inline: true }, { name: 'User', value: `${user}`, inline: true },
{ name: 'Moderator', value: `${mod}`, inline: true }, { name: 'Moderator', value: `${mod}`, inline: true },

View File

@ -30,10 +30,12 @@ export class BotAppreciationListener extends Listener {
public async run(message: Message) { public async run(message: Message) {
const content = message.content.toLowerCase(); const content = message.content.toLowerCase();
if (!content.includes('thanks arabot') if (
&& !content.includes('thanks ara bot') !content.includes('thanks arabot') &&
&& !content.includes('thank you arabot') !content.includes('thanks ara bot') &&
&& !content.includes('thank you ara bot')) { !content.includes('thank you arabot') &&
!content.includes('thank you ara bot')
) {
return; return;
} }

View File

@ -17,7 +17,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import type { UserError, MessageCommandDeniedPayload } from '@sapphire/framework'; import type {
UserError,
MessageCommandDeniedPayload,
} from '@sapphire/framework';
import { Listener } from '@sapphire/framework'; import { Listener } from '@sapphire/framework';
export class OldCommandDeniedListener extends Listener { export class OldCommandDeniedListener extends Listener {

View File

@ -46,7 +46,9 @@ export class XpListener extends Listener {
// If no counts exist on the database, then create the first count from the bot // If no counts exist on the database, then create the first count from the bot
if (lastCount === null) { if (lastCount === null) {
if (this.container.client.id === null) { if (this.container.client.id === null) {
message.channel.send('An unexpected error occurred trying to set up the counting channel, please contact a developer!'); message.channel.send(
'An unexpected error occurred trying to set up the counting channel, please contact a developer!',
);
return; return;
} }
@ -58,7 +60,9 @@ export class XpListener extends Listener {
lastCount = await getLastCount(); lastCount = await getLastCount();
if (lastCount === null) { if (lastCount === null) {
message.channel.send('An unexpected error occurred, please contact a developer!'); message.channel.send(
'An unexpected error occurred, please contact a developer!',
);
return; return;
} }
} }
@ -80,7 +84,9 @@ export class XpListener extends Listener {
// If the count was not correct, restart it // If the count was not correct, restart it
await addCount(message.author.id, 0); await addCount(message.author.id, 0);
await message.react('❌'); await message.react('❌');
await message.reply(`${message.author} counted incorrectly! The count got up to ${lastCount.number}! ` await message.reply(
+ 'The count has been reset and the next number is 1'); `${message.author} counted incorrectly! The count got up to ${lastCount.number}! ` +
'The count has been reset and the next number is 1',
);
} }
} }

View File

@ -20,7 +20,11 @@
import { Listener } from '@sapphire/framework'; import { Listener } from '@sapphire/framework';
import type { GuildMember } from 'discord.js'; import type { GuildMember } from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
import { addEmptyUser, logLeaving, updateUser } from '#utils/database/dbExistingUser'; import {
addEmptyUser,
logLeaving,
updateUser,
} from '#utils/database/dbExistingUser';
export class DbLeaveServerListener extends Listener { export class DbLeaveServerListener extends Listener {
public constructor(context: Listener.Context, options: Listener.Options) { public constructor(context: Listener.Context, options: Listener.Options) {
@ -31,10 +35,12 @@ export class DbLeaveServerListener extends Listener {
} }
public async run(member: GuildMember) { public async run(member: GuildMember) {
if (member.roles.cache.hasAny( if (
IDs.roles.vegan.vegan, member.roles.cache.hasAny(
IDs.roles.nonvegan.nonvegan, IDs.roles.vegan.vegan,
)) { IDs.roles.nonvegan.nonvegan,
)
) {
await updateUser(member); await updateUser(member);
} else { } else {
await addEmptyUser(member.id); await addEmptyUser(member.id);

View File

@ -17,7 +17,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import type { UserError, ChatInputCommandDeniedPayload } from '@sapphire/framework'; import type {
UserError,
ChatInputCommandDeniedPayload,
} from '@sapphire/framework';
import { Listener } from '@sapphire/framework'; import { Listener } from '@sapphire/framework';
export class CommandDeniedListener extends Listener { export class CommandDeniedListener extends Listener {

View File

@ -52,7 +52,7 @@ export class ModMailCreateListener extends Listener {
const userId = topic[2]; const userId = topic[2];
// Check if the user is currently restricted on the database // Check if the user is currently restricted on the database
if (!await checkActive(userId)) return; if (!(await checkActive(userId))) return;
// Get the restriction logs // Get the restriction logs
const restrictions = await getRestrictions(userId); const restrictions = await getRestrictions(userId);
@ -66,9 +66,11 @@ export class ModMailCreateListener extends Listener {
.setFooter({ text: `ID: ${userId}` }); .setFooter({ text: `ID: ${userId}` });
// Add up to 10 of the latest restrictions to the embed // Add up to 10 of the latest restrictions to the embed
for (let i = restrictions.length > 10 ? restrictions.length - 10 : 0; for (
let i = restrictions.length > 10 ? restrictions.length - 10 : 0;
i < restrictions.length; i < restrictions.length;
i += 1) { i += 1
) {
// Get mod names // Get mod names
let restMod = restrictions[i].modId; let restMod = restrictions[i].modId;
const restModMember = guild.members.cache.get(restMod); const restModMember = guild.members.cache.get(restMod);
@ -91,7 +93,9 @@ export class ModMailCreateListener extends Listener {
restTitle += 'Currently Restricted | '; restTitle += 'Currently Restricted | ';
} }
restTitle += `Date: <t:${Math.floor(restrictions[i].startTime.getTime() / 1000)}>`; restTitle += `Date: <t:${Math.floor(
restrictions[i].startTime.getTime() / 1000,
)}>`;
restrictEmbed.addFields({ restrictEmbed.addFields({
name: restTitle, name: restTitle,
@ -107,7 +111,11 @@ export class ModMailCreateListener extends Listener {
.setTitle(`${notes.length} sus notes`); .setTitle(`${notes.length} sus notes`);
// Add up to 10 of the latest sus notes to the embed // Add up to 10 of the latest sus notes to the embed
for (let i = notes.length > 10 ? notes.length - 10 : 0; i < notes.length; i += 1) { for (
let i = notes.length > 10 ? notes.length - 10 : 0;
i < notes.length;
i += 1
) {
// Get mod name // Get mod name
const modGuildMember = guild.members.cache.get(notes[i].modId); const modGuildMember = guild.members.cache.get(notes[i].modId);
let mod = notes[i].modId; let mod = notes[i].modId;
@ -116,7 +124,11 @@ export class ModMailCreateListener extends Listener {
} }
// Add sus note to embed // Add sus note to embed
susEmbed.addFields({ susEmbed.addFields({
name: `Sus ID: ${notes[i].id} | Moderator: ${mod} | Date: <t:${Math.floor(notes[i].time.getTime() / 1000)}>`, name: `Sus ID: ${
notes[i].id
} | Moderator: ${mod} | Date: <t:${Math.floor(
notes[i].time.getTime() / 1000,
)}>`,
value: notes[i].note, value: notes[i].note,
}); });
} }

View File

@ -20,10 +20,7 @@
import { Listener } from '@sapphire/framework'; import { Listener } from '@sapphire/framework';
import { ButtonStyle, ActionRowBuilder, ButtonBuilder } from 'discord.js'; import { ButtonStyle, ActionRowBuilder, ButtonBuilder } from 'discord.js';
import type { import type { Client, TextChannel } from 'discord.js';
Client,
TextChannel,
} from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
export class NonVeganAccessReady extends Listener { export class NonVeganAccessReady extends Listener {
@ -36,11 +33,13 @@ export class NonVeganAccessReady extends Listener {
} }
public async run(client: Client) { public async run(client: Client) {
let roles = client.channels.cache let roles = client.channels.cache.get(IDs.channels.information.roles) as
.get(IDs.channels.information.roles) as TextChannel | undefined; | TextChannel
| undefined;
if (roles === undefined) { if (roles === undefined) {
roles = await client.channels roles = (await client.channels.fetch(IDs.channels.information.roles)) as
.fetch(IDs.channels.information.roles) as TextChannel | undefined; | TextChannel
| undefined;
if (roles === undefined) { if (roles === undefined) {
this.container.logger.error('nonVeganAccess: Roles not found'); this.container.logger.error('nonVeganAccess: Roles not found');
return; return;
@ -51,17 +50,17 @@ export class NonVeganAccessReady extends Listener {
const messages = await roles.messages.fetch(); const messages = await roles.messages.fetch();
const message = messages.first(); const message = messages.first();
const content = '**Change access to non-vegan section of the server:**\n\n' const content =
+ 'If you\'re vegan and want your access removed/added back to the non vegan sections, ' '**Change access to non-vegan section of the server:**\n\n' +
+ 'press the button bellow to remove/gain access to the non vegan sections.'; "If you're vegan and want your access removed/added back to the non vegan sections, " +
'press the button bellow to remove/gain access to the non vegan sections.';
const button = new ActionRowBuilder<ButtonBuilder>() const button = new ActionRowBuilder<ButtonBuilder>().addComponents(
.addComponents( new ButtonBuilder()
new ButtonBuilder() .setCustomId('nvAccess')
.setCustomId('nvAccess') .setLabel('Non Vegan Access')
.setLabel('Non Vegan Access') .setStyle(ButtonStyle.Primary),
.setStyle(ButtonStyle.Primary), );
);
if (message?.author.id !== botId) { if (message?.author.id !== botId) {
await roles.send({ await roles.send({

View File

@ -71,9 +71,13 @@ export class RolesJoinServerListener extends Listener {
// Add user to the restricted vegan channel // Add user to the restricted vegan channel
if (section === 5) { if (section === 5) {
const restrictedCategory = member.guild.channels.cache.get(IDs.categories.restricted); const restrictedCategory = member.guild.channels.cache.get(
if (restrictedCategory !== undefined IDs.categories.restricted,
&& restrictedCategory.type === ChannelType.GuildCategory) { );
if (
restrictedCategory !== undefined &&
restrictedCategory.type === ChannelType.GuildCategory
) {
await this.restrictRun(member.id, restrictedCategory, member.guild); await this.restrictRun(member.id, restrictedCategory, member.guild);
} }
} }
@ -93,19 +97,28 @@ export class RolesJoinServerListener extends Listener {
await member.roles.add(roles); await member.roles.add(roles);
} }
const privateCategory = member.guild.channels.cache.get(IDs.categories.private); const privateCategory = member.guild.channels.cache.get(
IDs.categories.private,
);
if (privateCategory !== undefined if (
&& privateCategory.type === ChannelType.GuildCategory) { privateCategory !== undefined &&
privateCategory.type === ChannelType.GuildCategory
) {
await this.privateRun(member.id, privateCategory, member.guild); await this.privateRun(member.id, privateCategory, member.guild);
} }
// TODO add access back to diversity team // TODO add access back to diversity team
} }
private async restrictRun(userId: Snowflake, category: CategoryChannel, guild: Guild) { private async restrictRun(
const textChannels = category.children.cache userId: Snowflake,
.filter((c) => c.type === ChannelType.GuildText); category: CategoryChannel,
guild: Guild,
) {
const textChannels = category.children.cache.filter(
(c) => c.type === ChannelType.GuildText,
);
textChannels.forEach((c) => { textChannels.forEach((c) => {
const textChannel = c as TextChannel; const textChannel = c as TextChannel;
// Checks if the channel topic has the user's snowflake // Checks if the channel topic has the user's snowflake
@ -114,9 +127,11 @@ export class RolesJoinServerListener extends Listener {
const vcId = topic[topic.indexOf(userId) + 1]; const vcId = topic[topic.indexOf(userId) + 1];
const voiceChannel = guild.channels.cache.get(vcId); const voiceChannel = guild.channels.cache.get(vcId);
if (voiceChannel !== undefined if (
&& voiceChannel.parentId === IDs.categories.restricted voiceChannel !== undefined &&
&& voiceChannel.isVoiceBased()) { voiceChannel.parentId === IDs.categories.restricted &&
voiceChannel.isVoiceBased()
) {
voiceChannel.permissionOverwrites.edit(userId, { ViewChannel: true }); voiceChannel.permissionOverwrites.edit(userId, { ViewChannel: true });
} }
textChannel.permissionOverwrites.edit(userId, { ViewChannel: true }); textChannel.permissionOverwrites.edit(userId, { ViewChannel: true });
@ -124,9 +139,14 @@ export class RolesJoinServerListener extends Listener {
}); });
} }
private async privateRun(userId: Snowflake, category: CategoryChannel, guild: Guild) { private async privateRun(
const textChannels = category.children.cache userId: Snowflake,
.filter((c) => c.type === ChannelType.GuildText); category: CategoryChannel,
guild: Guild,
) {
const textChannels = category.children.cache.filter(
(c) => c.type === ChannelType.GuildText,
);
textChannels.forEach((c) => { textChannels.forEach((c) => {
const textChannel = c as TextChannel; const textChannel = c as TextChannel;
// Checks if the channel topic has the user's snowflake // Checks if the channel topic has the user's snowflake
@ -135,9 +155,11 @@ export class RolesJoinServerListener extends Listener {
const vcId = topic[topic.indexOf(userId) + 2]; const vcId = topic[topic.indexOf(userId) + 2];
const voiceChannel = guild.channels.cache.get(vcId); const voiceChannel = guild.channels.cache.get(vcId);
if (voiceChannel !== undefined if (
&& voiceChannel.parentId === IDs.categories.private voiceChannel !== undefined &&
&& voiceChannel.isVoiceBased()) { voiceChannel.parentId === IDs.categories.private &&
voiceChannel.isVoiceBased()
) {
voiceChannel.permissionOverwrites.edit(userId, { ViewChannel: true }); voiceChannel.permissionOverwrites.edit(userId, { ViewChannel: true });
} }
textChannel.permissionOverwrites.edit(userId, { ViewChannel: true }); textChannel.permissionOverwrites.edit(userId, { ViewChannel: true });

View File

@ -35,12 +35,14 @@ export class Suggestions extends Listener {
return; return;
} }
const mailbox = await this.container.client.channels.cache const mailbox = await this.container.client.channels.cache.get(
.get(IDs.channels.staff.mailbox); IDs.channels.staff.mailbox,
);
if (mailbox === undefined if (mailbox === undefined || !mailbox.isTextBased()) {
|| !mailbox.isTextBased()) { this.container.logger.error(
this.container.logger.error('Mailbox is not a TextBased channel or is undefined'); 'Mailbox is not a TextBased channel or is undefined',
);
return; return;
} }
@ -54,7 +56,10 @@ export class Suggestions extends Listener {
const suggestion = new EmbedBuilder() const suggestion = new EmbedBuilder()
.setColor('#FFFFFF') .setColor('#FFFFFF')
.setAuthor({ name: `Suggestion from ${message.author.tag}:`, iconURL: `${message.author.displayAvatarURL()}` }) .setAuthor({
name: `Suggestion from ${message.author.tag}:`,
iconURL: `${message.author.displayAvatarURL()}`,
})
.setTimestamp(); .setTimestamp();
if (message.content.length > 0) { if (message.content.length > 0) {
@ -66,9 +71,12 @@ export class Suggestions extends Listener {
suggestion.setFields({ name: 'Attachments', value: attachmentsString }); suggestion.setFields({ name: 'Attachments', value: attachmentsString });
} else { } else {
await message.delete(); await message.delete();
await message.author.send({ await message.author
content: 'There was an error sending your suggestion, please try again later or contact the devs!', .send({
}).catch(() => {}); content:
'There was an error sending your suggestion, please try again later or contact the devs!',
})
.catch(() => {});
return; return;
} }
@ -81,13 +89,16 @@ export class Suggestions extends Listener {
await sent.react('👍'); await sent.react('👍');
await sent.react('👎'); await sent.react('👎');
await sent.react('<:catshrug:917505035196313671>') await sent.react('<:catshrug:917505035196313671>').catch(() => {
.catch(() => { sent.react('🤷'); }); sent.react('🤷');
});
await message.author.send({ await message.author
content: 'Your suggestion has been sent!', .send({
embeds: [suggestion], content: 'Your suggestion has been sent!',
files: attachments, embeds: [suggestion],
}).catch(() => {}); files: attachments,
})
.catch(() => {});
} }
} }

View File

@ -35,7 +35,9 @@ export class VCMuteListener extends Listener {
const { member } = newState; const { member } = newState;
if (member === null) { if (member === null) {
this.container.logger.error('VCMute Listener - GuildMember not found when joining'); this.container.logger.error(
'VCMute Listener - GuildMember not found when joining',
);
return; return;
} }
@ -45,7 +47,7 @@ export class VCMuteListener extends Listener {
} }
// Check if user is muted on the database // Check if user is muted on the database
if (!await checkActive(member.id)) { if (!(await checkActive(member.id))) {
return; return;
} }
@ -59,12 +61,14 @@ export class VCMuteListener extends Listener {
const { member } = newState; const { member } = newState;
if (member === null) { if (member === null) {
this.container.logger.error('VCMute Listener - GuildMember not found when unmuting'); this.container.logger.error(
'VCMute Listener - GuildMember not found when unmuting',
);
return; return;
} }
// Check if user is muted on the database // Check if user is muted on the database
if (!await checkActive(member.id)) { if (!(await checkActive(member.id))) {
return; return;
} }

View File

@ -45,7 +45,11 @@ import {
finishVerifyMessages, finishVerifyMessages,
} from '#utils/verification'; } from '#utils/verification';
import { maxVCs, questionInfo, serverFind } from '#utils/verificationConfig'; import { maxVCs, questionInfo, serverFind } from '#utils/verificationConfig';
import { joinVerification, startVerification, finishVerification } from '#utils/database/verification'; import {
joinVerification,
startVerification,
finishVerification,
} from '#utils/database/verification';
import { findNotes } from '#utils/database/sus'; import { findNotes } from '#utils/database/sus';
import { addExistingUser } from '#utils/database/dbExistingUser'; import { addExistingUser } from '#utils/database/dbExistingUser';
import { rolesToString } from '#utils/formatter'; import { rolesToString } from '#utils/formatter';
@ -61,8 +65,9 @@ export class VerificationJoinVCListener extends Listener {
public async run(oldState: VoiceState, newState: VoiceState) { public async run(oldState: VoiceState, newState: VoiceState) {
// If the event was not a user joining the channel // If the event was not a user joining the channel
if (oldState.channel?.parent?.id === IDs.categories.verification if (
|| newState.channel?.parent?.id !== IDs.categories.verification oldState.channel?.parent?.id === IDs.categories.verification ||
newState.channel?.parent?.id !== IDs.categories.verification
) { ) {
return; return;
} }
@ -116,19 +121,22 @@ export class VerificationJoinVCListener extends Listener {
} }
// Checks if there is more than one person who has joined or if the channel has members // Checks if there is more than one person who has joined or if the channel has members
if (channel.members.size !== 1 if (channel.members.size !== 1 || !channel.members.has(member.id)) {
|| !channel.members.has(member.id)) {
return; return;
} }
// Check if the user has the verifiers role // Check if the user has the verifiers role
if (member.roles.cache.has(IDs.roles.staff.verifier) if (
|| member.roles.cache.has(IDs.roles.staff.trialVerifier)) { member.roles.cache.has(IDs.roles.staff.verifier) ||
member.roles.cache.has(IDs.roles.staff.trialVerifier)
) {
await channel.setName('Verifier Meeting'); await channel.setName('Verifier Meeting');
verifier = true; verifier = true;
} else { } else {
await currentChannel.send(`Hiya ${member.user}, please be patient as a verifier has been called out to verify you.\n\n` await currentChannel.send(
+ 'If you leave this voice channel, you will automatically be given the non-vegan role where you gain access to this server and if you\'d like to verify as a vegan again, you\'d have to contact a Mod, which could be done via ModMail.'); `Hiya ${member.user}, please be patient as a verifier has been called out to verify you.\n\n` +
"If you leave this voice channel, you will automatically be given the non-vegan role where you gain access to this server and if you'd like to verify as a vegan again, you'd have to contact a Mod, which could be done via ModMail.",
);
// Adds to the database that the user joined verification // Adds to the database that the user joined verification
await joinVerification(channel.id, member); await joinVerification(channel.id, member);
@ -143,22 +151,31 @@ export class VerificationJoinVCListener extends Listener {
]); ]);
// Start 15-minute timer if verifier does not join // Start 15-minute timer if verifier does not join
this.container.tasks.create('verifyTimeout', { this.container.tasks.create(
channelId: channel.id, 'verifyTimeout',
userId: member.id, {
}, 900_000); // 15 minutes channelId: channel.id,
userId: member.id,
},
900_000,
); // 15 minutes
} }
// Check how many voice channels there are // Check how many voice channels there are
const listVoiceChannels = category.children.cache const listVoiceChannels = category.children.cache.filter(
.filter((c) => c.type === ChannelType.GuildVoice); (c) => c.type === ChannelType.GuildVoice,
);
// Create a text channel for verifiers only // Create a text channel for verifiers only
if (!verifier) { if (!verifier) {
let verificationText: TextChannel; let verificationText: TextChannel;
let bannedName = false; let bannedName = false;
try { try {
verificationText = await createVerificationText(member, channel, category); verificationText = await createVerificationText(
member,
channel,
category,
);
} catch { } catch {
bannedName = true; bannedName = true;
verificationText = await createVerificationText( verificationText = await createVerificationText(
@ -184,7 +201,12 @@ export class VerificationJoinVCListener extends Listener {
embeds: [userInfoEmbed, susNotes], embeds: [userInfoEmbed, susNotes],
}); });
await this.verificationProcess(verificationText, channel.id, member, guild); await this.verificationProcess(
verificationText,
channel.id,
member,
guild,
);
} }
// Create a new channel for others to join // Create a new channel for others to join
@ -200,29 +222,37 @@ export class VerificationJoinVCListener extends Listener {
await currentChannel.permissionOverwrites.set([ await currentChannel.permissionOverwrites.set([
{ {
id: guild.roles.everyone, id: guild.roles.everyone,
deny: [PermissionsBitField.Flags.SendMessages, deny: [
PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.ViewChannel,
PermissionsBitField.Flags.Stream], PermissionsBitField.Flags.Stream,
],
}, },
{ {
id: IDs.roles.verifyBlock, id: IDs.roles.verifyBlock,
deny: [PermissionsBitField.Flags.ViewChannel, deny: [
PermissionsBitField.Flags.ViewChannel,
PermissionsBitField.Flags.Connect, PermissionsBitField.Flags.Connect,
PermissionsBitField.Flags.SendMessages], PermissionsBitField.Flags.SendMessages,
],
}, },
{ {
id: IDs.roles.staff.verifier, id: IDs.roles.staff.verifier,
allow: [PermissionsBitField.Flags.SendMessages, allow: [
PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.ViewChannel,
PermissionsBitField.Flags.Connect, PermissionsBitField.Flags.Connect,
PermissionsBitField.Flags.MuteMembers], PermissionsBitField.Flags.MuteMembers,
],
}, },
{ {
id: IDs.roles.staff.trialVerifier, id: IDs.roles.staff.trialVerifier,
allow: [PermissionsBitField.Flags.SendMessages, allow: [
PermissionsBitField.Flags.SendMessages,
PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.ViewChannel,
PermissionsBitField.Flags.Connect, PermissionsBitField.Flags.Connect,
PermissionsBitField.Flags.MuteMembers], PermissionsBitField.Flags.MuteMembers,
],
}, },
{ {
id: member.id, id: member.id,
@ -259,7 +289,11 @@ export class VerificationJoinVCListener extends Listener {
.setTitle(`${notes.length} sus notes for ${user.user.username}`); .setTitle(`${notes.length} sus notes for ${user.user.username}`);
// Add up to 10 of the latest sus notes to the embed // Add up to 10 of the latest sus notes to the embed
for (let i = notes.length > 10 ? notes.length - 10 : 0; i < notes.length; i += 1) { for (
let i = notes.length > 10 ? notes.length - 10 : 0;
i < notes.length;
i += 1
) {
// Get mod name // Get mod name
const modGuildMember = guild.members.cache.get(notes[i].modId); const modGuildMember = guild.members.cache.get(notes[i].modId);
let mod = notes[i].modId; let mod = notes[i].modId;
@ -268,7 +302,11 @@ export class VerificationJoinVCListener extends Listener {
} }
// Add sus note to embed // Add sus note to embed
embed.addFields({ embed.addFields({
name: `Sus ID: ${notes[i].id} | Moderator: ${mod} | Date: <t:${Math.floor(notes[i].time.getTime() / 1000)}>`, name: `Sus ID: ${
notes[i].id
} | Moderator: ${mod} | Date: <t:${Math.floor(
notes[i].time.getTime() / 1000,
)}>`,
value: notes[i].note, value: notes[i].note,
}); });
} }
@ -335,7 +373,10 @@ export class VerificationJoinVCListener extends Listener {
case 0: { case 0: {
info.find.reason = buttonChoice; info.find.reason = buttonChoice;
if (buttonChoice !== 0 && info.find.reason === 0) { if (buttonChoice !== 0 && info.find.reason === 0) {
embed = await this.createEmbed(serverFind[info.page].question, embedColor); embed = await this.createEmbed(
serverFind[info.page].question,
embedColor,
);
buttons = await this.createButtons(serverFind[info.page].buttons); buttons = await this.createButtons(serverFind[info.page].buttons);
await message.edit({ await message.edit({
embeds: [embed], embeds: [embed],
@ -405,7 +446,10 @@ export class VerificationJoinVCListener extends Listener {
info.page += 1; info.page += 1;
// Checks if finished all the questions // Checks if finished all the questions
if (info.page < questionLength) { if (info.page < questionLength) {
embed = await this.createEmbed(questionInfo[info.page].question, embedColor); embed = await this.createEmbed(
questionInfo[info.page].question,
embedColor,
);
buttons = await this.createButtons(questionInfo[info.page].buttons); buttons = await this.createButtons(questionInfo[info.page].buttons);
await message.edit({ await message.edit({
embeds: [embed], embeds: [embed],
@ -419,13 +463,14 @@ export class VerificationJoinVCListener extends Listener {
.setColor(embedColor) .setColor(embedColor)
.setTitle(`Give these roles to ${user.displayName}?`) .setTitle(`Give these roles to ${user.displayName}?`)
.setThumbnail(user.avatarURL()!) .setThumbnail(user.avatarURL()!)
.addFields( .addFields({
{ name: 'Roles:', value: this.getTextRoles(info.roles) }, name: 'Roles:',
); value: this.getTextRoles(info.roles),
});
// Create buttons for input // Create buttons for input
buttons = [new ActionRowBuilder<ButtonBuilder>() buttons = [
.addComponents( new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder() new ButtonBuilder()
.setCustomId('confirm') .setCustomId('confirm')
.setLabel('Yes') .setLabel('Yes')
@ -434,7 +479,8 @@ export class VerificationJoinVCListener extends Listener {
.setCustomId('cancel') .setCustomId('cancel')
.setLabel('No') .setLabel('No')
.setStyle(ButtonStyle.Danger), .setStyle(ButtonStyle.Danger),
)]; ),
];
await message.edit({ await message.edit({
embeds: [embed], embeds: [embed],
components: buttons, components: buttons,
@ -444,7 +490,9 @@ export class VerificationJoinVCListener extends Listener {
// Confirming and finishing the verification // Confirming and finishing the verification
if (button.customId === 'confirm' && info.page >= questionLength) { if (button.customId === 'confirm' && info.page >= questionLength) {
// Check verifier is on the database // Check verifier is on the database
const verifierGuildMember = await guild.members.cache.get(button.user.id); const verifierGuildMember = await guild.members.cache.get(
button.user.id,
);
if (verifierGuildMember === undefined) { if (verifierGuildMember === undefined) {
await message.edit({ content: 'Verifier not found!' }); await message.edit({ content: 'Verifier not found!' });
return; return;
@ -459,19 +507,21 @@ export class VerificationJoinVCListener extends Listener {
// Add timeout if they do not have activist role // Add timeout if they do not have activist role
if (!info.roles.activist) { if (!info.roles.activist) {
// @ts-ignore // @ts-ignore
this.container.tasks.create('verifyUnblock', { this.container.tasks.create(
userId: user.id, 'verifyUnblock',
guildId: guild.id, {
}, (info.roles.vegan || info.roles.convinced) ? 604800000 : 1814400000); userId: user.id,
guildId: guild.id,
},
info.roles.vegan || info.roles.convinced ? 604800000 : 1814400000,
);
} }
// Add embed saying verification completed // Add embed saying verification completed
embed = new EmbedBuilder() embed = new EmbedBuilder()
.setColor('#34c000') .setColor('#34c000')
.setTitle(`Successfully verified ${user.displayName}!`) .setTitle(`Successfully verified ${user.displayName}!`)
.setThumbnail(user.user.displayAvatarURL()) .setThumbnail(user.user.displayAvatarURL())
.addFields( .addFields({ name: 'Roles:', value: this.getTextRoles(info.roles) });
{ name: 'Roles:', value: this.getTextRoles(info.roles) },
);
await message.edit({ await message.edit({
embeds: [embed], embeds: [embed],
components: [], components: [],
@ -486,7 +536,10 @@ export class VerificationJoinVCListener extends Listener {
info.roles.trusted = false; info.roles.trusted = false;
info.roles.vegCurious = false; info.roles.vegCurious = false;
info.roles.convinced = false; info.roles.convinced = false;
embed = await this.createEmbed(questionInfo[info.page].question, embedColor); embed = await this.createEmbed(
questionInfo[info.page].question,
embedColor,
);
buttons = await this.createButtons(questionInfo[info.page].buttons); buttons = await this.createButtons(questionInfo[info.page].buttons);
await message.edit({ await message.edit({
embeds: [embed], embeds: [embed],
@ -498,9 +551,7 @@ export class VerificationJoinVCListener extends Listener {
} }
private async createEmbed(title: string, color: ColorResolvable) { private async createEmbed(title: string, color: ColorResolvable) {
return new EmbedBuilder() return new EmbedBuilder().setColor(color).setTitle(title);
.setColor(color)
.setTitle(title);
} }
private async createButtons(buttons: string[]) { private async createButtons(buttons: string[]) {
@ -511,13 +562,12 @@ export class VerificationJoinVCListener extends Listener {
if (i % 5 === 0) { if (i % 5 === 0) {
buttonActions.push(new ActionRowBuilder<ButtonBuilder>()); buttonActions.push(new ActionRowBuilder<ButtonBuilder>());
} }
buttonActions[Math.floor(i / 5)] buttonActions[Math.floor(i / 5)].addComponents(
.addComponents( new ButtonBuilder()
new ButtonBuilder() .setCustomId(`button${i}`)
.setCustomId(`button${i}`) .setLabel(buttons[i])
.setLabel(buttons[i]) .setStyle(ButtonStyle.Secondary),
.setStyle(ButtonStyle.Secondary), );
);
} }
return buttonActions; return buttonActions;
@ -532,15 +582,13 @@ export class VerificationJoinVCListener extends Listener {
return parseInt(buttonChoice, 10); return parseInt(buttonChoice, 10);
} }
private getTextRoles( private getTextRoles(roles: {
roles: { vegan: boolean;
vegan: boolean, activist: boolean;
activist: boolean, trusted: boolean;
trusted: boolean, vegCurious: boolean;
vegCurious: boolean, convinced: boolean;
convinced: boolean }) {
},
) {
let rolesText = ''; let rolesText = '';
if (roles.convinced) { if (roles.convinced) {
rolesText += `<@&${IDs.roles.nonvegan.convinced}>`; rolesText += `<@&${IDs.roles.nonvegan.convinced}>`;

View File

@ -19,12 +19,19 @@
import { Listener } from '@sapphire/framework'; import { Listener } from '@sapphire/framework';
import type { import type {
VoiceState, CategoryChannel, VoiceChannel, TextChannel, VoiceState,
CategoryChannel,
VoiceChannel,
TextChannel,
} from 'discord.js'; } from 'discord.js';
import { time, ChannelType } from 'discord.js'; import { time, ChannelType } from 'discord.js';
import { createVerificationVoice } from '#utils/verification'; import { createVerificationVoice } from '#utils/verification';
import { maxVCs, leaveBan } from '#utils/verificationConfig'; import { maxVCs, leaveBan } from '#utils/verificationConfig';
import { getUser, checkFinish, countIncomplete } from '#utils/database/verification'; import {
getUser,
checkFinish,
countIncomplete,
} from '#utils/database/verification';
import { fetchRoles } from '#utils/database/dbExistingUser'; import { fetchRoles } from '#utils/database/dbExistingUser';
import { fibonacci } from '#utils/maths'; import { fibonacci } from '#utils/maths';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
@ -39,9 +46,10 @@ export class VerificationLeaveVCListener extends Listener {
public async run(oldState: VoiceState, newState: VoiceState) { public async run(oldState: VoiceState, newState: VoiceState) {
// If the event was not a user joining the channel // If the event was not a user joining the channel
if (oldState.channel?.parent?.id !== IDs.categories.verification if (
|| newState.channel?.parent?.id === IDs.categories.verification oldState.channel?.parent?.id !== IDs.categories.verification ||
|| oldState.channel.members.size > 0 newState.channel?.parent?.id === IDs.categories.verification ||
oldState.channel.members.size > 0
) { ) {
return; return;
} }
@ -77,32 +85,48 @@ export class VerificationLeaveVCListener extends Listener {
const user = guild.members.cache.get(userSnowflake!); const user = guild.members.cache.get(userSnowflake!);
// Remove verify as vegan and give non vegan role // Remove verify as vegan and give non vegan role
if (!await checkFinish(channel.id) && user !== undefined) { if (!(await checkFinish(channel.id)) && user !== undefined) {
// Get roles to give back to the user // Get roles to give back to the user
const roles = await fetchRoles(user.id); const roles = await fetchRoles(user.id);
roles.push(IDs.roles.verifyBlock); roles.push(IDs.roles.verifyBlock);
await user.roles.add(roles) await user.roles
.catch(() => this.container.logger.error('Verification: User left but bot still tried to add roles')); .add(roles)
.catch(() =>
this.container.logger.error(
'Verification: User left but bot still tried to add roles',
),
);
// Create timeout block for user // Create timeout block for user
// Counts the recent times they have incomplete verifications // Counts the recent times they have incomplete verifications
const incompleteCount = await countIncomplete(user.id) % (leaveBan + 1); const incompleteCount =
(await countIncomplete(user.id)) % (leaveBan + 1);
// Creates the length of the time for the ban // Creates the length of the time for the ban
const banLength = fibonacci(incompleteCount) * 3600_000; const banLength = fibonacci(incompleteCount) * 3600_000;
this.container.tasks.create('verifyUnblock', { this.container.tasks.create(
userId: user.id, 'verifyUnblock',
guildId: guild.id, {
}, banLength); userId: user.id,
guildId: guild.id,
},
banLength,
);
await user.user.send('You have been timed out as a verifier had not joined for 15 minutes or you disconnected from verification.\n\n' await user.user
+ `You can verify again at: ${time(Math.round(Date.now() / 1000) + (banLength / 1000))}`) .send(
'You have been timed out as a verifier had not joined for 15 minutes or you disconnected from verification.\n\n' +
`You can verify again at: ${time(
Math.round(Date.now() / 1000) + banLength / 1000,
)}`,
)
.catch(() => this.container.logger.error('Verification: Closed DMs')); .catch(() => this.container.logger.error('Verification: Closed DMs'));
} }
} }
// Check how many voice channels there are // Check how many voice channels there are
const listVoiceChannels = category.children.cache const listVoiceChannels = category.children.cache.filter(
.filter((c) => c.type === ChannelType.GuildVoice); (c) => c.type === ChannelType.GuildVoice,
);
// Check that it is not deleting the 'Verification' channel (in case bot crashes) // Check that it is not deleting the 'Verification' channel (in case bot crashes)
if (channel.name !== 'Verification') { if (channel.name !== 'Verification') {
@ -113,8 +137,9 @@ export class VerificationLeaveVCListener extends Listener {
// Delete text channel // Delete text channel
if (!verifier) { if (!verifier) {
// Gets a list of all the text channels in the verification category // Gets a list of all the text channels in the verification category
const listTextChannels = category.children.cache const listTextChannels = category.children.cache.filter(
.filter((c) => c.type === ChannelType.GuildText); (c) => c.type === ChannelType.GuildText,
);
listTextChannels.forEach((c) => { listTextChannels.forEach((c) => {
const textChannel = c as TextChannel; const textChannel = c as TextChannel;
// Checks if the channel topic has the user's snowflake // Checks if the channel topic has the user's snowflake
@ -138,7 +163,9 @@ export class VerificationLeaveVCListener extends Listener {
const verification = listVoiceChannels.last() as VoiceChannel | undefined; const verification = listVoiceChannels.last() as VoiceChannel | undefined;
if (verification === undefined) { if (verification === undefined) {
this.container.logger.error('Verification: Verification channel not found.'); this.container.logger.error(
'Verification: Verification channel not found.',
);
return; return;
} }

View File

@ -39,11 +39,13 @@ export class VerificationReady extends Listener {
public async run(client: Client) { public async run(client: Client) {
// Get verification category // Get verification category
let category = client.channels.cache let category = client.channels.cache.get(IDs.categories.verification) as
.get(IDs.categories.verification) as CategoryChannel | undefined; | CategoryChannel
| undefined;
if (category === undefined) { if (category === undefined) {
category = await client.channels category = (await client.channels.fetch(IDs.categories.verification)) as
.fetch(IDs.categories.verification) as CategoryChannel | undefined; | CategoryChannel
| undefined;
if (category === undefined) { if (category === undefined) {
this.container.logger.error('verifyStart: Channel not found'); this.container.logger.error('verifyStart: Channel not found');
return; return;
@ -51,7 +53,9 @@ export class VerificationReady extends Listener {
} }
// Check how many voice channels there are // Check how many voice channels there are
const voiceChannels = category.children.cache.filter((c) => c.type === ChannelType.GuildVoice); const voiceChannels = category.children.cache.filter(
(c) => c.type === ChannelType.GuildVoice,
);
const currentVCs: VoiceChannel[] = []; const currentVCs: VoiceChannel[] = [];
const emptyVC: string[] = []; const emptyVC: string[] = [];
// Delete voice channels // Delete voice channels
@ -66,7 +70,9 @@ export class VerificationReady extends Listener {
}); });
// Delete text channels // Delete text channels
const textChannels = category.children.cache.filter((c) => c.type === ChannelType.GuildText); const textChannels = category.children.cache.filter(
(c) => c.type === ChannelType.GuildText,
);
textChannels.forEach((c) => { textChannels.forEach((c) => {
const textChannel = c as TextChannel; const textChannel = c as TextChannel;
// Checks if the channel topic has the user's snowflake // Checks if the channel topic has the user's snowflake

View File

@ -20,10 +20,7 @@
import { Listener } from '@sapphire/framework'; import { Listener } from '@sapphire/framework';
import { ButtonStyle, ActionRowBuilder, ButtonBuilder } from 'discord.js'; import { ButtonStyle, ActionRowBuilder, ButtonBuilder } from 'discord.js';
import type { import type { Client, TextChannel } from 'discord.js';
Client,
TextChannel,
} from 'discord.js';
import IDs from '#utils/ids'; import IDs from '#utils/ids';
export class VerificationReady extends Listener { export class VerificationReady extends Listener {
@ -37,9 +34,13 @@ export class VerificationReady extends Listener {
public async run(client: Client) { public async run(client: Client) {
// Get verification category // Get verification category
let welcome = client.channels.cache.get(IDs.channels.welcome) as TextChannel | undefined; let welcome = client.channels.cache.get(IDs.channels.welcome) as
| TextChannel
| undefined;
if (welcome === undefined) { if (welcome === undefined) {
welcome = await client.channels.fetch(IDs.channels.welcome) as TextChannel | undefined; welcome = (await client.channels.fetch(IDs.channels.welcome)) as
| TextChannel
| undefined;
if (welcome === undefined) { if (welcome === undefined) {
this.container.logger.error('verifyStart: Welcome not found'); this.container.logger.error('verifyStart: Welcome not found');
return; return;
@ -50,19 +51,19 @@ export class VerificationReady extends Listener {
const messages = await welcome.messages.fetch(); const messages = await welcome.messages.fetch();
const message = messages.first(); const message = messages.first();
const content = '**To continue and unlock more channels, please click \'Join\':**' const content =
+ '\n\n**Important:** If you want to get the vegan role, you will need to pass voice verification. ' "**To continue and unlock more channels, please click 'Join':**" +
+ 'You can do this by joining the \'Verification\' voice channel after clicking the button below. ' '\n\n**Important:** If you want to get the vegan role, you will need to pass voice verification. ' +
+ 'You\'ll chat with one of our verifiers who will just ask you a few questions before approving your Vegan role. ' "You can do this by joining the 'Verification' voice channel after clicking the button below. " +
+ 'Vegans have access to more channels. Voice discussions may be recorded.'; "You'll chat with one of our verifiers who will just ask you a few questions before approving your Vegan role. " +
'Vegans have access to more channels. Voice discussions may be recorded.';
const button = new ActionRowBuilder<ButtonBuilder>() const button = new ActionRowBuilder<ButtonBuilder>().addComponents(
.addComponents( new ButtonBuilder()
new ButtonBuilder() .setCustomId('welcomeJoin')
.setCustomId('welcomeJoin') .setLabel('Join')
.setLabel('Join') .setStyle(ButtonStyle.Success),
.setStyle(ButtonStyle.Success), );
);
if (message?.author.id !== botId) { if (message?.author.id !== botId) {
await welcome.send({ await welcome.send({

View File

@ -37,7 +37,7 @@ export class XpListener extends Listener {
return; return;
} }
if (!await checkCanAddXp(user.id)) { if (!(await checkCanAddXp(user.id))) {
return; return;
} }

View File

@ -37,7 +37,9 @@ export class CoordinatorOnlyPrecondition extends AllFlowsPrecondition {
return this.checkCoordinator(interaction.member! as GuildMember); return this.checkCoordinator(interaction.member! as GuildMember);
} }
public override async contextMenuRun(interaction: ContextMenuCommandInteraction) { public override async contextMenuRun(
interaction: ContextMenuCommandInteraction,
) {
// for context menu command // for context menu command
return this.checkCoordinator(interaction.member! as GuildMember); return this.checkCoordinator(interaction.member! as GuildMember);
} }

View File

@ -37,7 +37,9 @@ export class DevCoordinatorOnlyPrecondition extends AllFlowsPrecondition {
return this.checkDevCoordinator(interaction.member! as GuildMember); return this.checkDevCoordinator(interaction.member! as GuildMember);
} }
public override async contextMenuRun(interaction: ContextMenuCommandInteraction) { public override async contextMenuRun(
interaction: ContextMenuCommandInteraction,
) {
// for context menu command // for context menu command
return this.checkDevCoordinator(interaction.member! as GuildMember); return this.checkDevCoordinator(interaction.member! as GuildMember);
} }

View File

@ -37,7 +37,9 @@ export class DiversityCoordinatorOnlyPrecondition extends AllFlowsPrecondition {
return this.checkDiversityCoordinator(interaction.member! as GuildMember); return this.checkDiversityCoordinator(interaction.member! as GuildMember);
} }
public override async contextMenuRun(interaction: ContextMenuCommandInteraction) { public override async contextMenuRun(
interaction: ContextMenuCommandInteraction,
) {
// for context menu command // for context menu command
return this.checkDiversityCoordinator(interaction.member! as GuildMember); return this.checkDiversityCoordinator(interaction.member! as GuildMember);
} }
@ -45,7 +47,9 @@ export class DiversityCoordinatorOnlyPrecondition extends AllFlowsPrecondition {
private async checkDiversityCoordinator(user: GuildMember) { private async checkDiversityCoordinator(user: GuildMember) {
return user.roles.cache.has(IDs.roles.staff.diversityCoordinator) return user.roles.cache.has(IDs.roles.staff.diversityCoordinator)
? this.ok() ? this.ok()
: this.error({ message: 'Only diversity coordinators can run this command!' }); : this.error({
message: 'Only diversity coordinators can run this command!',
});
} }
} }

View File

@ -37,7 +37,9 @@ export class EventCoordinatorOnlyPrecondition extends AllFlowsPrecondition {
return this.checkEventCoordinator(interaction.member! as GuildMember); return this.checkEventCoordinator(interaction.member! as GuildMember);
} }
public override async contextMenuRun(interaction: ContextMenuCommandInteraction) { public override async contextMenuRun(
interaction: ContextMenuCommandInteraction,
) {
// for context menu command // for context menu command
return this.checkEventCoordinator(interaction.member! as GuildMember); return this.checkEventCoordinator(interaction.member! as GuildMember);
} }
@ -45,7 +47,9 @@ export class EventCoordinatorOnlyPrecondition extends AllFlowsPrecondition {
private async checkEventCoordinator(user: GuildMember) { private async checkEventCoordinator(user: GuildMember) {
return user.roles.cache.has(IDs.roles.staff.eventCoordinator) return user.roles.cache.has(IDs.roles.staff.eventCoordinator)
? this.ok() ? this.ok()
: this.error({ message: 'Only event coordinators can run this command!' }); : this.error({
message: 'Only event coordinators can run this command!',
});
} }
} }

View File

@ -37,7 +37,9 @@ export class MentorCoordinatorOnlyPrecondition extends AllFlowsPrecondition {
return this.checkMentorCoordinator(interaction.member! as GuildMember); return this.checkMentorCoordinator(interaction.member! as GuildMember);
} }
public override async contextMenuRun(interaction: ContextMenuCommandInteraction) { public override async contextMenuRun(
interaction: ContextMenuCommandInteraction,
) {
// for context menu command // for context menu command
return this.checkMentorCoordinator(interaction.member! as GuildMember); return this.checkMentorCoordinator(interaction.member! as GuildMember);
} }
@ -45,7 +47,9 @@ export class MentorCoordinatorOnlyPrecondition extends AllFlowsPrecondition {
private async checkMentorCoordinator(user: GuildMember) { private async checkMentorCoordinator(user: GuildMember) {
return user.roles.cache.has(IDs.roles.staff.mentorCoordinator) return user.roles.cache.has(IDs.roles.staff.mentorCoordinator)
? this.ok() ? this.ok()
: this.error({ message: 'Only mentor coordinators can run this command!' }); : this.error({
message: 'Only mentor coordinators can run this command!',
});
} }
} }

View File

@ -37,7 +37,9 @@ export class MentorOnlyPrecondition extends AllFlowsPrecondition {
return this.checkMentor(interaction.member! as GuildMember); return this.checkMentor(interaction.member! as GuildMember);
} }
public override async contextMenuRun(interaction: ContextMenuCommandInteraction) { public override async contextMenuRun(
interaction: ContextMenuCommandInteraction,
) {
// for context menu command // for context menu command
return this.checkMentor(interaction.member! as GuildMember); return this.checkMentor(interaction.member! as GuildMember);
} }

View File

@ -37,7 +37,9 @@ export class ModCoordinatorOnlyPrecondition extends AllFlowsPrecondition {
return this.checkModCoordinator(interaction.member! as GuildMember); return this.checkModCoordinator(interaction.member! as GuildMember);
} }
public override async contextMenuRun(interaction: ContextMenuCommandInteraction) { public override async contextMenuRun(
interaction: ContextMenuCommandInteraction,
) {
// for context menu command // for context menu command
return this.checkModCoordinator(interaction.member! as GuildMember); return this.checkModCoordinator(interaction.member! as GuildMember);
} }

Some files were not shown because too many files have changed in this diff Show More