mirror of
https://github.com/veganhacktivists/arabot.git
synced 2025-12-02 10:50:02 +01:00
Compare commits
157 Commits
topbal
...
132e3cc62b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
132e3cc62b | ||
|
|
db9204c115 | ||
|
|
0419488b6f | ||
|
|
2207d996a1 | ||
|
|
8f60c3eac9 | ||
|
|
c976905104 | ||
|
|
cd4526bfb1 | ||
|
|
e44c0c2037 | ||
|
|
9b3908cdc4 | ||
|
|
513d3ec581 | ||
|
|
2518376f3b | ||
|
|
f4f83e51b2 | ||
|
|
616334f123 | ||
|
|
cd319609b0 | ||
|
|
a1469e0596 | ||
|
|
ca0e43a70e | ||
|
|
dc16dee92c | ||
|
|
71f0ee9f01 | ||
|
|
881f9bfc24 | ||
|
|
98b9ac6fde | ||
|
|
1f92bf5d68 | ||
|
|
d9f04e8d49 | ||
|
|
b4c8f0785c | ||
|
|
7918f73e7d | ||
|
|
ea211a9111 | ||
|
|
32776a2311 | ||
|
|
d72b66f988 | ||
|
|
e03bd6e85e | ||
|
|
a400cf9507 | ||
|
|
2fbb6c9265 | ||
|
|
fc8c12b346 | ||
|
|
9ebf8a6938 | ||
|
|
bc7f2ffcfd | ||
|
|
86f391e131 | ||
|
|
63c3b14b1c | ||
|
|
a5187ec567 | ||
|
|
222c3cb81a | ||
|
|
8f8580398e | ||
|
|
fe88e9f87b | ||
|
|
4ad35f5b57 | ||
|
|
1c9f6612a3 | ||
|
|
88dd678bdc | ||
|
|
9c51be9ab6 | ||
|
|
128b15f18f | ||
|
|
dba9aa970e | ||
|
|
0ac0ff7f5c | ||
|
|
ae0afa02db | ||
|
|
3009a0f923 | ||
|
|
a09b007831 | ||
|
|
325dc0d0d0 | ||
|
|
71a065d3ca | ||
|
|
613f53491b | ||
|
|
19721c10ea | ||
|
|
bd87a8b6c6 | ||
|
|
46ef2fd8e2 | ||
|
|
d8c91fd39b | ||
|
|
fabd381051 | ||
|
|
a5758dc6ef | ||
|
|
9ff5b78aff | ||
|
|
f4655829e2 | ||
|
|
c82d256be4 | ||
|
|
a9039572d1 | ||
|
|
2cf7998cd9 | ||
|
|
63a4d651af | ||
|
|
a2dba859f2 | ||
|
|
a7b772f77a | ||
|
|
1fa87b8a4a | ||
|
|
4e99a5456f | ||
|
|
62d941dfcb | ||
|
|
e6b1463a1a | ||
|
|
5793bbb461 | ||
|
|
cf8142b86a | ||
|
|
502d5c5cdf | ||
|
|
8f071b8043 | ||
|
|
36ce086532 | ||
|
|
617834833a | ||
|
|
4d92250500 | ||
|
|
f898dada56 | ||
|
|
9e2f2c7558 | ||
|
|
e15e5da5aa | ||
|
|
e89f056b94 | ||
|
|
6acd012e7a | ||
|
|
75174f711d | ||
|
|
5e69ea6126 | ||
|
|
3d8aba5577 | ||
|
|
e7839552f8 | ||
|
|
3b0666e80d | ||
|
|
3d8a9be7f2 | ||
|
|
a7f608c1f0 | ||
|
|
cb457136d4 | ||
|
|
7e984c4857 | ||
|
|
0ea9ea3f64 | ||
|
|
19e70ebdbc | ||
|
|
5409be3d75 | ||
|
|
edd3caf9c0 | ||
|
|
5a87f97a74 | ||
|
|
feab05c1ea | ||
|
|
9b505fbece | ||
|
|
a5ba493372 | ||
|
|
98e514b5e9 | ||
|
|
172508c741 | ||
|
|
730f3e6a28 | ||
|
|
fbc2944b92 | ||
|
|
6172dc6ac6 | ||
|
|
b762ae3bc8 | ||
|
|
c8eb8299dd | ||
|
|
785e844da8 | ||
|
|
b3afe3f162 | ||
|
|
5bbc5057fc | ||
|
|
7943a2d1b8 | ||
|
|
3a4f8dba78 | ||
|
|
f4eac3cbe7 | ||
|
|
fe655ea0dc | ||
|
|
a95b1fde6e | ||
|
|
aad5066ba9 | ||
|
|
8302e11436 | ||
|
|
8c48473ef3 | ||
|
|
d90c985cec | ||
|
|
b6b50ea450 | ||
|
|
d00fddd51a | ||
|
|
e5f2c9436e | ||
|
|
0bb10b55ed | ||
|
|
d9c4f54299 | ||
|
|
77bbe97c6a | ||
|
|
a498cde933 | ||
|
|
750b10062f | ||
|
|
e348b09f80 | ||
|
|
4dc37ab31c | ||
|
|
396d69db06 | ||
|
|
94036984d3 | ||
|
|
0068fb5bdd | ||
|
|
1f3610a89d | ||
|
|
02298f2089 | ||
|
|
bb6ac8aef0 | ||
|
|
3f82f87317 | ||
|
|
fc2574e8e1 | ||
|
|
619aeb533b | ||
|
|
255ca62c33 | ||
|
|
ef0cf08bf8 | ||
|
|
113ebbbaee | ||
|
|
4a03675256 | ||
|
|
7fa844c24f | ||
|
|
5a42926c13 | ||
|
|
54f1c23c69 | ||
|
|
b3e1d11e72 | ||
|
|
d42332f290 | ||
|
|
534453fcc0 | ||
|
|
6fbb547ca7 | ||
|
|
a1beb4d347 | ||
|
|
48b30bfcb9 | ||
|
|
165a34ba0c | ||
|
|
c9a987a2a9 | ||
|
|
7aebbbc2fd | ||
|
|
779f8de43f | ||
|
|
0e77867010 | ||
|
|
c58360d563 | ||
|
|
3bf351e472 |
@@ -1,6 +1,6 @@
|
|||||||
.idea
|
.idea
|
||||||
dist
|
dist
|
||||||
node_modules
|
node_modules
|
||||||
tsconfig.tsbuildinfo
|
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
.env
|
.env
|
||||||
|
*.md
|
||||||
|
|||||||
10
.env.example
10
.env.example
@@ -3,16 +3,18 @@ DISCORD_TOKEN= # Bot token from: https://discord.com/developers/
|
|||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
DEFAULT_PREFIX= # Prefix used to run commands in Discord
|
DEFAULT_PREFIX= # Prefix used to run commands in Discord
|
||||||
DEVELOPMENT= # (true/false) Enables developer mode
|
DEVELOPMENT= # (true/false) Enables developer mode
|
||||||
|
|
||||||
# Docker
|
# Docker
|
||||||
POSTGRES_USER=USERNAME
|
POSTGRES_USER=USERNAME
|
||||||
POSTGRES_PASSWORD=PASSWORD
|
POSTGRES_PASSWORD=PASSWORD
|
||||||
POSTGRES_DB=DB
|
POSTGRES_DB=DB
|
||||||
|
|
||||||
# Redis
|
# Redis (if running everything within docker compose, use "redis" for the host and leave the rest empty)
|
||||||
REDIS_URL= # URL to redis database (if running everything within docker compose, use "redis")
|
REDIS_HOST= # URL to redis database
|
||||||
BULLMQ_URL # URL for redis database, but without redis:// and credentials
|
REDIS_USER= # redis database user
|
||||||
|
REDIS_PASSWORD= # redis database password
|
||||||
|
REDIS_PORT= # redis database port
|
||||||
|
|
||||||
# Database URL (designed for Postgres, but designed on Prisma)
|
# Database URL (designed for Postgres, but designed on Prisma)
|
||||||
DATABASE_URL= # "postgresql://USERNAME:PASSWORD@postgres:5432/DB?schema=ara&sslmode=prefer"
|
DATABASE_URL= # "postgresql://USERNAME:PASSWORD@postgres:5432/DB?schema=ara&sslmode=prefer"
|
||||||
|
|||||||
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
|||||||
|
|
||||||
# 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@v3
|
||||||
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.
|
||||||
@@ -55,7 +55,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v2
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
@@ -68,4 +68,4 @@ jobs:
|
|||||||
# ./location_of_script_within_repo/buildscript.sh
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v3
|
||||||
|
|||||||
2
.github/workflows/eslint.yml
vendored
2
.github/workflows/eslint.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Upload analysis results to GitHub
|
- name: Upload analysis results to GitHub
|
||||||
uses: github/codeql-action/upload-sarif@v2
|
uses: github/codeql-action/upload-sarif@v3
|
||||||
with:
|
with:
|
||||||
sarif_file: eslint-results.sarif
|
sarif_file: eslint-results.sarif
|
||||||
wait-for-processing: true
|
wait-for-processing: true
|
||||||
|
|||||||
3
.npmrc
Normal file
3
.npmrc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
node-linker=hoisted
|
||||||
|
shamefully-hoist=true
|
||||||
|
public-hoist-pattern[]=@sapphire/*
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
dist
|
dist
|
||||||
node_modules
|
node_modules
|
||||||
|
tsconfig.json
|
||||||
|
pnpm-lock.yaml
|
||||||
|
|||||||
36
Dockerfile
36
Dockerfile
@@ -1,24 +1,26 @@
|
|||||||
FROM node:20
|
FROM node:22 AS base
|
||||||
|
# PNPM
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /opt/app
|
COPY . /app
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
FROM base AS prod-deps
|
||||||
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
|
||||||
|
|
||||||
COPY --chown=node:node package.json .
|
FROM base AS build
|
||||||
COPY --chown=node:node package-lock.json .
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
||||||
COPY --chown=node:node tsconfig.json .
|
RUN pnpm exec prisma generate
|
||||||
COPY --chown=node:node prisma ./prisma/
|
RUN pnpm run build
|
||||||
|
|
||||||
RUN npm install
|
FROM base
|
||||||
|
COPY --from=prod-deps /app/node_modules /app/node_modules
|
||||||
|
COPY --from=build /app/node_modules/.prisma /app/node_modules/.prisma
|
||||||
|
COPY --from=build /app/dist /app/dist
|
||||||
|
|
||||||
COPY . .
|
RUN chown node:node .
|
||||||
|
|
||||||
RUN npx prisma generate
|
|
||||||
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
RUN chown node:node /opt/app/
|
|
||||||
|
|
||||||
USER node
|
USER node
|
||||||
|
CMD [ "pnpm", "run", "start:migrate"]
|
||||||
CMD [ "npm", "run", "start:migrate"]
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
version: '3.7'
|
version: '3.7'
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:15
|
image: postgres:16
|
||||||
container_name: postgres
|
container_name: postgres
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
|
|||||||
5
nixpacks.toml
Normal file
5
nixpacks.toml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[phases.build]
|
||||||
|
cmds = ["pnpm prisma generate", "..."]
|
||||||
|
|
||||||
|
[start]
|
||||||
|
cmd = 'pnpm run start:migrate'
|
||||||
4436
package-lock.json
generated
4436
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
55
package.json
55
package.json
@@ -4,10 +4,11 @@
|
|||||||
"description": "A Discord bot for Animal Rights Advocates",
|
"description": "A Discord bot for Animal Rights Advocates",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"preinstall": "npx only-allow pnpm",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"cleanBuild": "rm -rf ./dist && tsc",
|
"cleanBuild": "rm -rf ./dist && tsc",
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"start:migrate": "prisma migrate deploy && npm run start"
|
"start:migrate": "prisma migrate deploy && pnpm run start"
|
||||||
},
|
},
|
||||||
"imports": {
|
"imports": {
|
||||||
"#utils/*": "./dist/utils/*.js"
|
"#utils/*": "./dist/utils/*.js"
|
||||||
@@ -28,31 +29,35 @@
|
|||||||
"url": "https://github.com/veganhacktivists/arabot/issues"
|
"url": "https://github.com/veganhacktivists/arabot/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/veganhacktivists/arabot#readme",
|
"homepage": "https://github.com/veganhacktivists/arabot#readme",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20",
|
||||||
|
"pnpm": ">=9"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^5.5.2",
|
"@prisma/client": "^6.2.1",
|
||||||
"@sapphire/discord.js-utilities": "^7.0.2",
|
"@sapphire/discord.js-utilities": "^7.3.2",
|
||||||
"@sapphire/framework": "^4.7.2",
|
"@sapphire/framework": "^5.3.2",
|
||||||
"@sapphire/plugin-logger": "^3.0.6",
|
"@sapphire/plugin-logger": "^4.0.2",
|
||||||
"@sapphire/plugin-scheduled-tasks": "^8.0.0",
|
"@sapphire/plugin-scheduled-tasks": "^10.0.2",
|
||||||
"@sapphire/plugin-subcommands": "^5.0.0",
|
"@sapphire/plugin-subcommands": "^7.0.1",
|
||||||
"@sapphire/stopwatch": "^1.5.0",
|
"@sapphire/stopwatch": "^1.5.4",
|
||||||
"@sapphire/time-utilities": "^1.7.10",
|
"@sapphire/time-utilities": "^1.7.14",
|
||||||
"@sapphire/ts-config": "^5.0.0",
|
"@sapphire/ts-config": "^5.0.1",
|
||||||
"@sapphire/utilities": "^3.13.0",
|
"@sapphire/utilities": "^3.18.1",
|
||||||
"@types/node": "^20.8.9",
|
"bullmq": "^5.34.10",
|
||||||
"bullmq": "^4.12.7",
|
"discord.js": "^14.17.3",
|
||||||
"discord.js": "^14.13.0",
|
"ioredis": "^5.4.2",
|
||||||
"redis": "^4.6.10",
|
"ts-node": "^10.9.2",
|
||||||
"ts-node": "^10.9.1",
|
"typescript": "~5.4.5"
|
||||||
"typescript": "^5.2.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/ioredis": "^5.0.0",
|
"@types/node": "^22.10.7",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
||||||
"@typescript-eslint/parser": "^6.9.0",
|
"@typescript-eslint/parser": "^8.20.0",
|
||||||
"eslint": "8.54.0",
|
"eslint": "9.18.0",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
"prettier": "3.1.0",
|
"prettier": "3.4.2",
|
||||||
"prisma": "^5.5.2"
|
"prisma": "^6.2.1"
|
||||||
}
|
},
|
||||||
|
"packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228"
|
||||||
}
|
}
|
||||||
|
|||||||
1783
pnpm-lock.yaml
generated
Normal file
1783
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `active` on the `Warning` table. All the data in the column will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Warning" DROP COLUMN "active";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- Added the required column `channelId` to the `StatRole` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "StatRole" ADD COLUMN "channelId" TEXT NOT NULL;
|
||||||
@@ -222,9 +222,10 @@ model Stat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model StatRole {
|
model StatRole {
|
||||||
stat Stat @relation(fields: [statId], references: [id])
|
stat Stat @relation(fields: [statId], references: [id])
|
||||||
statId Int @id
|
statId Int @id
|
||||||
roleId String
|
roleId String
|
||||||
|
channelId String
|
||||||
}
|
}
|
||||||
|
|
||||||
model ParticipantStat {
|
model ParticipantStat {
|
||||||
@@ -256,7 +257,6 @@ model Warning {
|
|||||||
mod User @relation("warnMod", fields: [modId], references: [id])
|
mod User @relation("warnMod", fields: [modId], references: [id])
|
||||||
modId String
|
modId String
|
||||||
time DateTime @default(now())
|
time DateTime @default(now())
|
||||||
active Boolean @default(true)
|
|
||||||
note String
|
note String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { ChannelType } from 'discord.js';
|
import { MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { isRole, isUser } from '#utils/typeChecking';
|
||||||
|
import { isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class AccessCommand extends Command {
|
export class AccessCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'access',
|
name: 'access',
|
||||||
@@ -79,7 +81,7 @@ export class AccessCommand extends Command {
|
|||||||
if (!interaction.inCachedGuild()) {
|
if (!interaction.inCachedGuild()) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'This command can only be run in a server!',
|
content: 'This command can only be run in a server!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -91,32 +93,29 @@ export class AccessCommand extends Command {
|
|||||||
const role = interaction.options.getRole('role');
|
const role = interaction.options.getRole('role');
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (user === null && role === null) {
|
if (!isUser(user) && !isRole(role)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching slash command data!',
|
content: 'Error fetching slash command data!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 (isUser(user) && isRole(role)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content:
|
content:
|
||||||
'You have entered a user and a role at the same time! Please only enter one at a time.',
|
'You have entered a user and a role at the same time! Please only enter one at a time.',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
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 (
|
if (!isTextChannel(channel) && !channel.isVoiceBased()) {
|
||||||
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,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -129,7 +128,7 @@ export class AccessCommand extends Command {
|
|||||||
) {
|
) {
|
||||||
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,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -143,13 +142,13 @@ export class AccessCommand extends Command {
|
|||||||
} else {
|
} else {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not find the role to edit permissions!',
|
content: 'Could not find the role to edit permissions!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set permissions of voice channel
|
// Set permissions of voice channel
|
||||||
if (channel.type === ChannelType.GuildVoice) {
|
if (channel.isVoiceBased()) {
|
||||||
switch (permission) {
|
switch (permission) {
|
||||||
case 'add':
|
case 'add':
|
||||||
await channel.permissionOverwrites.create(permId, {
|
await channel.permissionOverwrites.create(permId, {
|
||||||
@@ -185,7 +184,7 @@ export class AccessCommand extends Command {
|
|||||||
default:
|
default:
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Incorrect permission option!',
|
content: 'Incorrect permission option!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -220,7 +219,7 @@ export class AccessCommand extends Command {
|
|||||||
default:
|
default:
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Incorrect permission option!',
|
content: 'Incorrect permission option!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Message } from 'discord.js';
|
import { Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import { ChannelType, TextChannel } from 'discord.js';
|
import { ChannelType, TextChannel } from 'discord.js';
|
||||||
|
import { isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class AnonymousCommand extends Command {
|
export class AnonymousCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'anonymous',
|
name: 'anonymous',
|
||||||
@@ -67,18 +68,27 @@ export class AnonymousCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel === null) {
|
if (channel === null) {
|
||||||
if (interaction.channel === null) {
|
if (!isTextChannel(interaction.channel)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error getting the channel!',
|
content: 'Error getting the channel!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!interaction.channel.isSendable()) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: `I do not have sufficient permissions to send a message in ${interaction.channel}!`,
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -86,8 +96,8 @@ export class AnonymousCommand extends Command {
|
|||||||
await interaction.channel.send(message);
|
await interaction.channel.send(message);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Sent the message',
|
content: 'Sent the message',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -95,8 +105,8 @@ export class AnonymousCommand extends Command {
|
|||||||
if (channel.type !== ChannelType.GuildText) {
|
if (channel.type !== ChannelType.GuildText) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not send, unsupported text channel!',
|
content: 'Could not send, unsupported text channel!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,8 +115,8 @@ export class AnonymousCommand extends Command {
|
|||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Sent the message',
|
content: 'Sent the message',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +131,7 @@ export class AnonymousCommand extends Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel.isTextBased()) {
|
if (channel.isSendable()) {
|
||||||
await channel.send(text);
|
await channel.send(text);
|
||||||
} else {
|
} else {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
|
|||||||
@@ -18,10 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Message } from 'discord.js';
|
import { Message, MessageFlagsBitField } from 'discord.js';
|
||||||
|
import { isGuildBasedChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class ClearCommand extends Command {
|
export class ClearCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'clear',
|
name: 'clear',
|
||||||
@@ -57,11 +58,11 @@ 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 || channel.isDMBased()) {
|
if (!isGuildBasedChannel(channel)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not fetch channel!',
|
content: 'Could not fetch channel!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -70,8 +71,8 @@ export class ClearCommand extends Command {
|
|||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Successfully deleted ${messages} messages!`,
|
content: `Successfully deleted ${messages} messages!`,
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ export class ClearCommand extends Command {
|
|||||||
|
|
||||||
const { channel } = message;
|
const { channel } = message;
|
||||||
|
|
||||||
if (!channel.isTextBased() || channel.isDMBased()) {
|
if (!isGuildBasedChannel(channel)) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply('Unsupported channel type!');
|
await message.reply('Unsupported channel type!');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -19,9 +19,8 @@
|
|||||||
|
|
||||||
import { RegisterBehavior } from '@sapphire/framework';
|
import { RegisterBehavior } from '@sapphire/framework';
|
||||||
import { Subcommand } from '@sapphire/plugin-subcommands';
|
import { Subcommand } from '@sapphire/plugin-subcommands';
|
||||||
import type { Guild, TextChannel, Snowflake } from 'discord.js';
|
import { TextChannel, Snowflake, MessageFlagsBitField } from 'discord.js';
|
||||||
import {
|
import {
|
||||||
CategoryChannel,
|
|
||||||
ChannelType,
|
ChannelType,
|
||||||
EmbedBuilder,
|
EmbedBuilder,
|
||||||
GuildMember,
|
GuildMember,
|
||||||
@@ -29,9 +28,25 @@ import {
|
|||||||
time,
|
time,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import {
|
||||||
|
isCategoryChannel,
|
||||||
|
isGuildBasedChannel,
|
||||||
|
isGuildMember,
|
||||||
|
isTextChannel,
|
||||||
|
isVoiceChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
import {
|
||||||
|
getCategoryChannel,
|
||||||
|
getGuildMember,
|
||||||
|
getVoiceChannel,
|
||||||
|
} from '#utils/fetcher';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class PrivateCommand extends Subcommand {
|
export class PrivateCommand extends Subcommand {
|
||||||
public constructor(context: Subcommand.Context, options: Subcommand.Options) {
|
public constructor(
|
||||||
|
context: Subcommand.LoaderContext,
|
||||||
|
options: Subcommand.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'private',
|
name: 'private',
|
||||||
@@ -90,7 +105,9 @@ export class PrivateCommand extends Subcommand {
|
|||||||
const modUser = interaction.user;
|
const modUser = interaction.user;
|
||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -100,11 +117,11 @@ export class PrivateCommand extends Subcommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const mod = guild.members.cache.get(modUser.id);
|
const mod = await getGuildMember(modUser.id, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (member === undefined || mod === undefined) {
|
if (!isGuildMember(member) || !isGuildMember(mod)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'Error fetching users!',
|
content: 'Error fetching users!',
|
||||||
});
|
});
|
||||||
@@ -113,7 +130,7 @@ export class PrivateCommand extends Subcommand {
|
|||||||
|
|
||||||
const [name, coordinator] = this.getCoordinator(mod);
|
const [name, coordinator] = this.getCoordinator(mod);
|
||||||
|
|
||||||
if (this.checkPrivate(member.id, coordinator, guild)) {
|
if (await this.checkPrivate(member.id, coordinator)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'A private channel already exists!',
|
content: 'A private channel already exists!',
|
||||||
});
|
});
|
||||||
@@ -232,20 +249,22 @@ export class PrivateCommand extends Subcommand {
|
|||||||
const modUser = interaction.user;
|
const modUser = interaction.user;
|
||||||
const { guild, channel } = interaction;
|
const { guild, channel } = interaction;
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (guild === null || channel === null) {
|
if (guild === null || !isGuildBasedChannel(channel)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'Error fetching user!',
|
content: 'Error fetching user!',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = guild.members.cache.get(modUser.id);
|
const mod = await getGuildMember(modUser.id, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (mod === undefined) {
|
if (!isGuildMember(mod)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'Error fetching users!',
|
content: 'Error fetching users!',
|
||||||
});
|
});
|
||||||
@@ -256,8 +275,8 @@ export class PrivateCommand extends Subcommand {
|
|||||||
const coordinator = coordinatorInfo[1];
|
const coordinator = coordinatorInfo[1];
|
||||||
let topic: string[];
|
let topic: string[];
|
||||||
|
|
||||||
if (user === null) {
|
if (!isUser(user)) {
|
||||||
if (channel.type !== ChannelType.GuildText) {
|
if (!isTextChannel(channel)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content:
|
content:
|
||||||
'Please make sure you ran this command in the original private text channel!',
|
'Please make sure you ran this command in the original private text channel!',
|
||||||
@@ -284,10 +303,10 @@ export class PrivateCommand extends Subcommand {
|
|||||||
await channel.delete();
|
await channel.delete();
|
||||||
|
|
||||||
const vcId = topic[topic.indexOf(coordinator) + 1];
|
const vcId = topic[topic.indexOf(coordinator) + 1];
|
||||||
const voiceChannel = guild.channels.cache.get(vcId);
|
const voiceChannel = await getVoiceChannel(vcId);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
voiceChannel !== undefined &&
|
isVoiceChannel(voiceChannel) &&
|
||||||
voiceChannel.parentId === IDs.categories.private
|
voiceChannel.parentId === IDs.categories.private
|
||||||
) {
|
) {
|
||||||
await voiceChannel.delete();
|
await voiceChannel.delete();
|
||||||
@@ -295,9 +314,7 @@ export class PrivateCommand extends Subcommand {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const category = guild.channels.cache.get(IDs.categories.private) as
|
const category = await getCategoryChannel(IDs.categories.private);
|
||||||
| CategoryChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (category === undefined) {
|
if (category === undefined) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
@@ -306,26 +323,32 @@ export class PrivateCommand extends Subcommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const textChannels = category.children.cache.filter(
|
const textChannels = category.children.cache.filter((channel) =>
|
||||||
(c) => c.type === ChannelType.GuildText,
|
isTextChannel(channel),
|
||||||
);
|
);
|
||||||
textChannels.forEach((c) => {
|
|
||||||
const textChannel = c as TextChannel;
|
for (const c of textChannels) {
|
||||||
|
const channel = c[1];
|
||||||
|
|
||||||
|
if (!isTextChannel(channel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 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?.id)) {
|
if (channel.topic !== null && channel.topic.includes(user.id)) {
|
||||||
topic = textChannel.topic.split(' ');
|
topic = channel.topic.split(' ');
|
||||||
const vcId = topic[topic.indexOf(coordinator) + 1];
|
const vcId = topic[topic.indexOf(coordinator) + 1];
|
||||||
const voiceChannel = guild.channels.cache.get(vcId);
|
const voiceChannel = await getVoiceChannel(vcId);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
voiceChannel !== undefined &&
|
isVoiceChannel(voiceChannel) &&
|
||||||
voiceChannel.parentId === IDs.categories.private
|
voiceChannel.parentId === IDs.categories.private
|
||||||
) {
|
) {
|
||||||
voiceChannel.delete();
|
await voiceChannel.delete();
|
||||||
}
|
}
|
||||||
textChannel.delete();
|
await channel.delete();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `Successfully deleted the channel for ${user}`,
|
content: `Successfully deleted the channel for ${user}`,
|
||||||
@@ -353,6 +376,12 @@ export class PrivateCommand extends Subcommand {
|
|||||||
} else if (user.roles.cache.has(IDs.roles.staff.eventCoordinator)) {
|
} else if (user.roles.cache.has(IDs.roles.staff.eventCoordinator)) {
|
||||||
name = 'event';
|
name = 'event';
|
||||||
id = IDs.roles.staff.eventCoordinator;
|
id = IDs.roles.staff.eventCoordinator;
|
||||||
|
} else if (user.roles.cache.has(IDs.roles.staff.mediaCoordinator)) {
|
||||||
|
name = 'media';
|
||||||
|
id = IDs.roles.staff.mediaCoordinator;
|
||||||
|
} else if (user.roles.cache.has(IDs.roles.staff.hrCoordinator)) {
|
||||||
|
name = 'hr';
|
||||||
|
id = IDs.roles.staff.hrCoordinator;
|
||||||
} else {
|
} else {
|
||||||
name = 'coordinator';
|
name = 'coordinator';
|
||||||
id = IDs.roles.staff.coordinator;
|
id = IDs.roles.staff.coordinator;
|
||||||
@@ -360,29 +389,35 @@ export class PrivateCommand extends Subcommand {
|
|||||||
return [name, id];
|
return [name, id];
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkPrivate(user: Snowflake, coordinator: string, guild: Guild) {
|
private async checkPrivate(user: Snowflake, coordinator: string) {
|
||||||
const category = guild.channels.cache.get(IDs.categories.private) as
|
const category = await getCategoryChannel(IDs.categories.private);
|
||||||
| CategoryChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (category === undefined) {
|
if (!isCategoryChannel(category)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const textChannels = category.children.cache.filter(
|
const textChannels = category.children.cache.filter(
|
||||||
(c) => c.type === ChannelType.GuildText,
|
(c) => c.type === ChannelType.GuildText,
|
||||||
);
|
);
|
||||||
|
|
||||||
let exists = false;
|
let exists = false;
|
||||||
textChannels.forEach((c) => {
|
|
||||||
const textChannel = c as TextChannel;
|
for (const c of textChannels) {
|
||||||
|
const channel = c[1];
|
||||||
|
|
||||||
|
if (!isTextChannel(channel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Checks if the channel topic has the user's snowflake
|
// Checks if the channel topic has the user's snowflake
|
||||||
if (
|
if (
|
||||||
textChannel.topic?.includes(user) &&
|
channel.topic !== null &&
|
||||||
textChannel.topic?.includes(coordinator)
|
channel.topic.includes(user) &&
|
||||||
|
channel.topic.includes(coordinator)
|
||||||
) {
|
) {
|
||||||
exists = true;
|
exists = true;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,13 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { User, Guild, Message } from 'discord.js';
|
import { User, Guild, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import { updateUser } from '#utils/database/dbExistingUser';
|
import { updateUser } from '#utils/database/dbExistingUser';
|
||||||
import { getBalance } from '#utils/database/economy';
|
import { getBalance } from '#utils/database/fun/economy';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
|
import { getGuildMember } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class BalanceCommand extends Command {
|
export class BalanceCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'balance',
|
name: 'balance',
|
||||||
@@ -50,7 +52,7 @@ export class BalanceCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not find the guild!',
|
content: 'Could not find the guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -66,15 +68,9 @@ export class BalanceCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async messageRun(message: Message) {
|
public async messageRun(message: Message) {
|
||||||
const user = message.member?.user;
|
const user = message.author;
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (user === undefined) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Could not find your user!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply('Could not find the guild!');
|
await message.reply('Could not find the guild!');
|
||||||
@@ -99,9 +95,9 @@ export class BalanceCommand extends Command {
|
|||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Could not find your guild member!';
|
info.message = 'Could not find your guild member!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,22 @@
|
|||||||
|
|
||||||
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 { User, Guild, GuildMember, Message } from 'discord.js';
|
import {
|
||||||
|
User,
|
||||||
|
Guild,
|
||||||
|
GuildMember,
|
||||||
|
Message,
|
||||||
|
MessageFlagsBitField,
|
||||||
|
} 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/fun/economy';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getGuildMember } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class DailyCommand extends Command {
|
export class DailyCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'daily',
|
name: 'daily',
|
||||||
@@ -51,7 +59,7 @@ export class DailyCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not find the guild!',
|
content: 'Could not find the guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -67,15 +75,9 @@ export class DailyCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async messageRun(message: Message) {
|
public async messageRun(message: Message) {
|
||||||
const user = message.member?.user;
|
const user = message.author;
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (user === undefined) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Could not find your user!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply('Could not find the guild!');
|
await message.reply('Could not find the guild!');
|
||||||
@@ -114,9 +116,9 @@ export class DailyCommand extends Command {
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Could not find your guild member!';
|
info.message = 'Could not find your guild member!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { User, Guild, Message } from 'discord.js';
|
import { User, Guild, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import { updateUser } from '#utils/database/dbExistingUser';
|
import { updateUser } from '#utils/database/dbExistingUser';
|
||||||
import { getBalance, transfer } from '#utils/database/economy';
|
import { getBalance, transfer } from '#utils/database/fun/economy';
|
||||||
import { EmbedBuilder, TextChannel } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getGuildMember, getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import { isGuildMember, isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class BalanceCommand extends Command {
|
export class BalanceCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'pay',
|
name: 'pay',
|
||||||
@@ -75,7 +77,7 @@ export class BalanceCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not find the guild!',
|
content: 'Could not find the guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -117,15 +119,9 @@ export class BalanceCommand extends Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = message.member?.user;
|
const user = message.author;
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (user === undefined) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Could not find your user!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply('Could not find the guild!');
|
await message.reply('Could not find the guild!');
|
||||||
@@ -164,15 +160,15 @@ export class BalanceCommand extends Command {
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const recipientMember = guild.members.cache.get(recipient.id);
|
const recipientMember = await getGuildMember(recipient.id, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Could not find your guild member!';
|
info.message = 'Could not find your guild member!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipientMember === undefined) {
|
if (!isGuildMember(recipientMember)) {
|
||||||
info.message = 'Could not find the user!';
|
info.message = 'Could not find the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -206,18 +202,16 @@ 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.get(IDs.channels.logs.economy) as
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.economy);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (logChannel === undefined) {
|
if (!isTextChannel(logChannel)) {
|
||||||
logChannel = (await guild.channels.fetch(IDs.channels.logs.economy)) as
|
this.container.logger.error('Pay: Could not fetch log channel');
|
||||||
| TextChannel
|
return info;
|
||||||
| undefined;
|
} else if (!logChannel.isSendable()) {
|
||||||
if (logChannel === undefined) {
|
this.container.logger.error(
|
||||||
this.container.logger.error('Pay Error: Could not fetch log channel');
|
'Pay: the bot does not have permission to send in the log channel',
|
||||||
return info;
|
);
|
||||||
}
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const logEmbed = new EmbedBuilder(embed.data);
|
const logEmbed = new EmbedBuilder(embed.data);
|
||||||
|
|||||||
@@ -18,17 +18,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import { N1984 } from '#utils/gifs';
|
import { N1984 } from '#utils/gifs';
|
||||||
import { addFunLog, countTotal } from '#utils/database/fun';
|
import { addFunLog, countTotal } from '#utils/database/fun/fun';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class N1984Command extends Command {
|
export class N1984Command extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: '1984',
|
name: '1984',
|
||||||
description: 'this is literally 1984',
|
description: 'this is literally 1984',
|
||||||
preconditions: ['ModOnly'],
|
preconditions: [['CoordinatorOnly', 'ModOnly']],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,10 +46,26 @@ export class N1984Command extends Command {
|
|||||||
// Command run
|
// Command run
|
||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the user
|
// Get the user
|
||||||
const { user } = interaction;
|
const { member } = interaction;
|
||||||
|
|
||||||
await addFunLog(user.id, '1984');
|
// Type checks
|
||||||
const count = await countTotal(user.id, '1984');
|
if (!isGuildMember(member)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Failed to fetch your user on the bot!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await addFunLog(member.id, '1984');
|
||||||
|
const count = await countTotal(member.id, '1984');
|
||||||
|
|
||||||
|
let embedFooter: string;
|
||||||
|
if (count === 1) {
|
||||||
|
embedFooter = `${member.displayName} 1984'd the server for the first time!`;
|
||||||
|
} else {
|
||||||
|
embedFooter = `${member.displayName} 1984'd the server ${count} times!`;
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@@ -58,11 +75,11 @@ export class N1984Command extends Command {
|
|||||||
: N1984[Math.floor(Math.random() * N1984.length)];
|
: 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(`${member.displayName} is happy!`)
|
||||||
.setImage(random1984)
|
.setImage(random1984)
|
||||||
.setFooter({ text: `${user.username}'s 1984 count: ${count}` });
|
.setFooter({ text: embedFooter });
|
||||||
|
|
||||||
// Send the embed
|
// Send the embed
|
||||||
await interaction.reply({ embeds: [n1984Embed], fetchReply: true });
|
await interaction.reply({ embeds: [n1984Embed], withResponse: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import { Cringe } from '#utils/gifs';
|
import { Cringe } from '#utils/gifs';
|
||||||
import { addFunLog, countTotal } from '#utils/database/fun';
|
import { addFunLog, countTotal } from '#utils/database/fun/fun';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class CringeCommand extends Command {
|
export class CringeCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'cringe',
|
name: 'cringe',
|
||||||
@@ -44,21 +45,36 @@ export class CringeCommand extends Command {
|
|||||||
// Command run
|
// Command run
|
||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the user
|
// Get the user
|
||||||
// TODO exception handling
|
const { member } = interaction;
|
||||||
const { user } = interaction;
|
|
||||||
|
|
||||||
await addFunLog(user.id, 'cringe');
|
// Type check
|
||||||
const count = await countTotal(user.id, 'cringe');
|
if (!isGuildMember(member)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Failed to fetch your user on the bot!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await addFunLog(member.id, 'cringe');
|
||||||
|
const count = await countTotal(member.id, 'cringe');
|
||||||
|
|
||||||
|
let embedFooter: string;
|
||||||
|
if (count === 1) {
|
||||||
|
embedFooter = `${member.displayName} cringed for the first time!`;
|
||||||
|
} else {
|
||||||
|
embedFooter = `${member.displayName} cringed ${count} times!`;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates the embed for the cringe reaction
|
// Creates the embed for the cringe reaction
|
||||||
const randomCringe = Cringe[Math.floor(Math.random() * Cringe.length)];
|
const randomCringe = Cringe[Math.floor(Math.random() * Cringe.length)];
|
||||||
const cringeEmbed = new EmbedBuilder()
|
const cringeEmbed = new EmbedBuilder()
|
||||||
.setColor('#001148')
|
.setColor('#001148')
|
||||||
.setTitle(`${user.username} feels immense cringe...`)
|
.setTitle(`${member.displayName} feels immense cringe...`)
|
||||||
.setImage(randomCringe)
|
.setImage(randomCringe)
|
||||||
.setFooter({ text: `${user.username}'s cringe count: ${count}` });
|
.setFooter({ text: embedFooter });
|
||||||
|
|
||||||
// Send the embed
|
// Send the embed
|
||||||
await interaction.reply({ embeds: [cringeEmbed], fetchReply: true });
|
await interaction.reply({ embeds: [cringeEmbed], withResponse: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import { Happy } from '#utils/gifs';
|
import { Happy } from '#utils/gifs';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class HappyCommand extends Command {
|
export class HappyCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'happy',
|
name: 'happy',
|
||||||
description: 'Express your happiness',
|
description: 'Express your happiness',
|
||||||
preconditions: [['CoordinatorOnly', 'PatreonOnly']],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,18 +44,25 @@ export class HappyCommand extends Command {
|
|||||||
// Command run
|
// Command run
|
||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the user
|
// Get the user
|
||||||
// TODO exception handling
|
const { member } = interaction;
|
||||||
const member = interaction.member!.user;
|
|
||||||
const memberGuildMember = interaction.guild!.members.cache.get(member.id)!;
|
// Type checks
|
||||||
|
if (!isGuildMember(member)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Failed to fetch your user on the bot!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates the embed for the happy reaction
|
// Creates the embed for the happy reaction
|
||||||
const randomHappy = Happy[Math.floor(Math.random() * Happy.length)];
|
const randomHappy = Happy[Math.floor(Math.random() * Happy.length)];
|
||||||
const happyEmbed = new EmbedBuilder()
|
const happyEmbed = new EmbedBuilder()
|
||||||
.setColor('#40ff00')
|
.setColor('#40ff00')
|
||||||
.setTitle(`${memberGuildMember.displayName} is happy!`)
|
.setTitle(`${member.displayName} is happy!`)
|
||||||
.setImage(randomHappy);
|
.setImage(randomHappy);
|
||||||
|
|
||||||
// Send the embed
|
// Send the embed
|
||||||
await interaction.reply({ embeds: [happyEmbed], fetchReply: true });
|
await interaction.reply({ embeds: [happyEmbed], withResponse: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import { Hugs } from '#utils/gifs';
|
import { Hugs } from '#utils/gifs';
|
||||||
import { addFunLog, countTotal } from '#utils/database/fun';
|
import { addFunLog, countTotal } from '#utils/database/fun/fun';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class HugCommand extends Command {
|
export class HugCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'hug',
|
name: 'hug',
|
||||||
@@ -54,26 +55,49 @@ export class HugCommand extends Command {
|
|||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the users
|
// Get the users
|
||||||
const user = interaction.options.getUser('user', true);
|
const user = interaction.options.getUser('user', true);
|
||||||
const hugger = interaction.user;
|
const hugger = interaction.member;
|
||||||
|
|
||||||
|
// Type Checks
|
||||||
|
|
||||||
|
if (!isGuildMember(hugger)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Failed to fetch your user on the bot!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await addFunLog(hugger.id, 'hug', user.id);
|
await addFunLog(hugger.id, 'hug', user.id);
|
||||||
const count = await countTotal(hugger.id, 'hug', user.id);
|
const count = await countTotal(hugger.id, 'hug', user.id);
|
||||||
|
|
||||||
|
let embedFooter: string;
|
||||||
|
if (hugger.id === user.id) {
|
||||||
|
if (count === 1) {
|
||||||
|
embedFooter = `You hugged yourself for the first time!`;
|
||||||
|
} else {
|
||||||
|
embedFooter = `You hugged yourself ${count} times!`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (count === 1) {
|
||||||
|
embedFooter = `${hugger.displayName} hugged you for the first time!`;
|
||||||
|
} else {
|
||||||
|
embedFooter = `${hugger.displayName} hugged you ${count} times!`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Creates the embed for the hug
|
// Creates the embed for the hug
|
||||||
const randomHug = Hugs[Math.floor(Math.random() * Hugs.length)];
|
const randomHug = Hugs[Math.floor(Math.random() * Hugs.length)];
|
||||||
const hugEmbed = new EmbedBuilder()
|
const hugEmbed = new EmbedBuilder()
|
||||||
.setColor('#0099ff')
|
.setColor('#0099ff')
|
||||||
.setTitle(`Hug from ${hugger.username}`)
|
.setTitle(`Hug from ${hugger.displayName}`)
|
||||||
.setImage(randomHug)
|
.setImage(randomHug)
|
||||||
.setFooter({
|
.setFooter({ text: embedFooter });
|
||||||
text: `Amount of hugs given from ${hugger.username} to you: ${count}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send the hug
|
// Send the hug
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `${user}`,
|
content: `${user}`,
|
||||||
embeds: [hugEmbed],
|
embeds: [hugEmbed],
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import { Kill } from '#utils/gifs';
|
import { Kill } from '#utils/gifs';
|
||||||
import { addFunLog, countTotal } from '#utils/database/fun';
|
import { addFunLog, countTotal } from '#utils/database/fun/fun';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class KillCommand extends Command {
|
export class KillCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'kill',
|
name: 'kill',
|
||||||
@@ -54,7 +55,16 @@ export class KillCommand extends Command {
|
|||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the users
|
// Get the users
|
||||||
const user = interaction.options.getUser('user', true)!;
|
const user = interaction.options.getUser('user', true)!;
|
||||||
const sender = interaction.user;
|
const sender = interaction.member;
|
||||||
|
|
||||||
|
// Type checks
|
||||||
|
if (!isGuildMember(sender)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Failed to fetch your user on the bot!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (user.id === sender.id) {
|
if (user.id === sender.id) {
|
||||||
await interaction.reply('You changed your mind');
|
await interaction.reply('You changed your mind');
|
||||||
@@ -64,21 +74,26 @@ export class KillCommand extends Command {
|
|||||||
await addFunLog(sender.id, 'kill', user.id);
|
await addFunLog(sender.id, 'kill', user.id);
|
||||||
const count = await countTotal(sender.id, 'kill', user.id);
|
const count = await countTotal(sender.id, 'kill', user.id);
|
||||||
|
|
||||||
|
let embedFooter: string;
|
||||||
|
if (count === 1) {
|
||||||
|
embedFooter = `${sender.displayName} killed you for the first time!`;
|
||||||
|
} else {
|
||||||
|
embedFooter = `${sender.displayName} killed you ${count} times!`;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates the embed for the kill
|
// Creates the embed for the kill
|
||||||
const randomKill = Kill[Math.floor(Math.random() * Kill.length)];
|
const randomKill = Kill[Math.floor(Math.random() * Kill.length)];
|
||||||
const killEmbed = new EmbedBuilder()
|
const killEmbed = new EmbedBuilder()
|
||||||
.setColor('#ff0000')
|
.setColor('#ff0000')
|
||||||
.setTitle(`Kill from ${sender.username}`)
|
.setTitle(`Kill from ${sender.displayName}`)
|
||||||
.setImage(randomKill)
|
.setImage(randomKill)
|
||||||
.setFooter({
|
.setFooter({ text: embedFooter });
|
||||||
text: `Amount of kills from ${sender.username} to you: ${count}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send the kill
|
// Send the kill
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `${user}`,
|
content: `${user}`,
|
||||||
embeds: [killEmbed],
|
embeds: [killEmbed],
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import { Poke } from '#utils/gifs';
|
import { Poke } from '#utils/gifs';
|
||||||
import { addFunLog, countTotal } from '#utils/database/fun';
|
import { addFunLog, countTotal } from '#utils/database/fun/fun';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class PokeCommand extends Command {
|
export class PokeCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'poke',
|
name: 'poke',
|
||||||
@@ -54,26 +55,48 @@ export class PokeCommand extends Command {
|
|||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the users
|
// Get the users
|
||||||
const user = interaction.options.getUser('user', true)!;
|
const user = interaction.options.getUser('user', true)!;
|
||||||
const sender = interaction.user;
|
const sender = interaction.member;
|
||||||
|
|
||||||
|
// Type checks
|
||||||
|
if (!isGuildMember(sender)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Failed to fetch your user on the bot!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await addFunLog(sender.id, 'poke', user.id);
|
await addFunLog(sender.id, 'poke', user.id);
|
||||||
const count = await countTotal(sender.id, 'poke', user.id);
|
const count = await countTotal(sender.id, 'poke', user.id);
|
||||||
|
|
||||||
|
let embedFooter: string;
|
||||||
|
if (sender.id === user.id) {
|
||||||
|
if (count === 1) {
|
||||||
|
embedFooter = `You poked yourself for the first time!`;
|
||||||
|
} else {
|
||||||
|
embedFooter = `You poked yourself ${count} times!`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (count === 1) {
|
||||||
|
embedFooter = `${sender.displayName} poked you for the first time!`;
|
||||||
|
} else {
|
||||||
|
embedFooter = `${sender.displayName} poked you ${count} times!`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Creates the embed for the poke
|
// Creates the embed for the poke
|
||||||
const randomPoke = Poke[Math.floor(Math.random() * Poke.length)];
|
const randomPoke = Poke[Math.floor(Math.random() * Poke.length)];
|
||||||
const pokeEmbed = new EmbedBuilder()
|
const pokeEmbed = new EmbedBuilder()
|
||||||
.setColor('#0099ff')
|
.setColor('#0099ff')
|
||||||
.setTitle(`Poke from ${sender.username}`)
|
.setTitle(`Poke from ${sender.displayName}`)
|
||||||
.setImage(randomPoke)
|
.setImage(randomPoke)
|
||||||
.setFooter({
|
.setFooter({ text: embedFooter });
|
||||||
text: `Amount of pokes from ${sender.username} to you: ${count}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send the poke
|
// Send the poke
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `${user}`,
|
content: `${user}`,
|
||||||
embeds: [pokeEmbed],
|
embeds: [pokeEmbed],
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import { Sad } from '#utils/gifs';
|
import { Sad } from '#utils/gifs';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class SadCommand extends Command {
|
export class SadCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'sad',
|
name: 'sad',
|
||||||
description: 'Express your sadness',
|
description: 'Express your sadness',
|
||||||
preconditions: [['CoordinatorOnly', 'PatreonOnly']],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,18 +44,25 @@ export class SadCommand extends Command {
|
|||||||
// Command run
|
// Command run
|
||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the user
|
// Get the user
|
||||||
// TODO exception handling
|
const { member } = interaction;
|
||||||
const member = interaction.member!.user;
|
|
||||||
const memberGuildMember = interaction.guild!.members.cache.get(member.id)!;
|
// Type checks
|
||||||
|
if (!isGuildMember(member)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Failed to fetch your user on the bot!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates the embed for the sad reaction
|
// Creates the embed for the sad reaction
|
||||||
const randomSad = Sad[Math.floor(Math.random() * Sad.length)];
|
const randomSad = Sad[Math.floor(Math.random() * Sad.length)];
|
||||||
const sadEmbed = new EmbedBuilder()
|
const sadEmbed = new EmbedBuilder()
|
||||||
.setColor('#001148')
|
.setColor('#001148')
|
||||||
.setTitle(`${memberGuildMember.displayName} is sad...`)
|
.setTitle(`${member.displayName} is sad...`)
|
||||||
.setImage(randomSad);
|
.setImage(randomSad);
|
||||||
|
|
||||||
// Send the embed
|
// Send the embed
|
||||||
await interaction.reply({ embeds: [sadEmbed], fetchReply: true });
|
await interaction.reply({ embeds: [sadEmbed], withResponse: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import { Shrug } from '#utils/gifs';
|
import { Shrug } from '#utils/gifs';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class ShrugCommand extends Command {
|
export class ShrugCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'shrug',
|
name: 'shrug',
|
||||||
description: 'Ugh... whatever... idk...',
|
description: 'Ugh... whatever... idk...',
|
||||||
preconditions: [['CoordinatorOnly', 'PatreonOnly']],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,18 +44,25 @@ export class ShrugCommand extends Command {
|
|||||||
// Command run
|
// Command run
|
||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the user
|
// Get the user
|
||||||
// TODO exception handling
|
const { member } = interaction;
|
||||||
const member = interaction.member!.user;
|
|
||||||
const memberGuildMember = interaction.guild!.members.cache.get(member.id)!;
|
// Type checks
|
||||||
|
if (!isGuildMember(member)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Failed to fetch your user on the bot!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates the embed for the shrug reaction
|
// Creates the embed for the shrug reaction
|
||||||
const randomShrug = Shrug[Math.floor(Math.random() * Shrug.length)];
|
const randomShrug = Shrug[Math.floor(Math.random() * Shrug.length)];
|
||||||
const shrugEmbed = new EmbedBuilder()
|
const shrugEmbed = new EmbedBuilder()
|
||||||
.setColor('#001980')
|
.setColor('#001980')
|
||||||
.setTitle(`${memberGuildMember.displayName} shrugs`)
|
.setTitle(`${member.displayName} shrugs`)
|
||||||
.setImage(randomShrug);
|
.setImage(randomShrug);
|
||||||
|
|
||||||
// Send the embed
|
// Send the embed
|
||||||
await interaction.reply({ embeds: [shrugEmbed], fetchReply: true });
|
await interaction.reply({ embeds: [shrugEmbed], withResponse: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,15 +18,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { User, Message, Snowflake, TextChannel, Guild } from 'discord.js';
|
import {
|
||||||
|
User,
|
||||||
|
Message,
|
||||||
|
Snowflake,
|
||||||
|
Guild,
|
||||||
|
MessageFlagsBitField,
|
||||||
|
} 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/moderation/ban';
|
||||||
import { addEmptyUser, updateUser } from '#utils/database/dbExistingUser';
|
import { addEmptyUser, updateUser } from '#utils/database/dbExistingUser';
|
||||||
import { checkTempBan, removeTempBan } from '#utils/database/tempBan';
|
import {
|
||||||
|
checkTempBan,
|
||||||
|
removeTempBan,
|
||||||
|
} from '#utils/database/moderation/tempBan';
|
||||||
|
import { getGuildMember, getTextBasedChannel, getUser } from '#utils/fetcher';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
import {
|
||||||
|
isGuildMember,
|
||||||
|
isTextBasedChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class BanCommand extends Command {
|
export class BanCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'ban',
|
name: 'ban',
|
||||||
@@ -72,13 +87,15 @@ export class BanCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const ban = await this.ban(user.id, mod.id, reason, guild);
|
const ban = await this.ban(user.id, mod.id, reason, guild);
|
||||||
|
|
||||||
@@ -139,17 +156,19 @@ export class BanCommand extends Command {
|
|||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = guild.client.users.cache.get(userId);
|
const user = await getUser(userId);
|
||||||
|
|
||||||
if (user === undefined) {
|
if (!isUser(user)) {
|
||||||
user = (await guild.client.users.fetch(userId)) as User;
|
info.message =
|
||||||
|
'The user does not exist! (The user provided is probably wrong, or their account has been deleted.)';
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets mod's GuildMember
|
// Gets mod's GuildMember
|
||||||
const mod = guild.members.cache.get(modId);
|
const mod = await getGuildMember(modId, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (mod === undefined) {
|
if (!isGuildMember(mod)) {
|
||||||
info.message = 'Error fetching mod!';
|
info.message = 'Error fetching mod!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -163,13 +182,9 @@ export class BanCommand extends Command {
|
|||||||
await updateUser(mod);
|
await updateUser(mod);
|
||||||
|
|
||||||
// Gets guildMember
|
// Gets guildMember
|
||||||
let member = guild.members.cache.get(userId);
|
const member = await getGuildMember(userId, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (isGuildMember(member)) {
|
||||||
member = await guild.members.fetch(userId).catch(() => undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (member !== undefined) {
|
|
||||||
// Checks if the user is not restricted
|
// Checks if the user is not restricted
|
||||||
if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
||||||
info.message = 'You need to restrict the user first!';
|
info.message = 'You need to restrict the user first!';
|
||||||
@@ -203,19 +218,20 @@ export class BanCommand extends Command {
|
|||||||
info.success = true;
|
info.success = true;
|
||||||
|
|
||||||
// Log the ban
|
// Log the ban
|
||||||
let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.restricted);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (logChannel === undefined) {
|
if (!isTextBasedChannel(logChannel)) {
|
||||||
logChannel = (await guild.channels.fetch(
|
this.container.logger.error('Ban: Could not fetch log channel');
|
||||||
IDs.channels.logs.restricted,
|
info.message = `${user} has been banned. This hasn't been logged in a text channel as log channel could not be found`;
|
||||||
)) as TextChannel | undefined;
|
|
||||||
if (logChannel === undefined) {
|
return info;
|
||||||
this.container.logger.error('Ban Error: Could not fetch log channel');
|
} else if (!logChannel.isSendable()) {
|
||||||
info.message = `${user} has been banned. This hasn't been logged in a text channel as log channel could not be found`;
|
this.container.logger.error(
|
||||||
return info;
|
'Ban: The bot does not have permission to send in the logs channel!',
|
||||||
}
|
);
|
||||||
|
info.message = `${user} has been banned. This hasn't been logged in a text channel as the bot does not have permission to send logs!`;
|
||||||
|
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const log = new EmbedBuilder()
|
const log = new EmbedBuilder()
|
||||||
|
|||||||
@@ -19,14 +19,20 @@
|
|||||||
|
|
||||||
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 { User, Snowflake, TextChannel, Guild } from 'discord.js';
|
import { User, Snowflake, Guild, MessageFlagsBitField } 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/moderation/tempBan';
|
||||||
import { addEmptyUser, updateUser } from '#utils/database/dbExistingUser';
|
import { addEmptyUser, updateUser } from '#utils/database/dbExistingUser';
|
||||||
|
import { getGuildMember, getTextBasedChannel, getUser } from '#utils/fetcher';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
import {
|
||||||
|
isGuildMember,
|
||||||
|
isTextBasedChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class TempBanCommand extends Command {
|
export class TempBanCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'tempban',
|
name: 'tempban',
|
||||||
@@ -79,8 +85,8 @@ export class TempBanCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -94,7 +100,9 @@ export class TempBanCommand extends Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const ban = await this.ban(user.id, mod.id, time, reason, guild);
|
const ban = await this.ban(user.id, mod.id, time, reason, guild);
|
||||||
|
|
||||||
@@ -201,17 +209,19 @@ export class TempBanCommand extends Command {
|
|||||||
|
|
||||||
const banLength = new DurationFormatter().format(time.offset);
|
const banLength = new DurationFormatter().format(time.offset);
|
||||||
|
|
||||||
let user = guild.client.users.cache.get(userId);
|
const user = await getUser(userId);
|
||||||
|
|
||||||
if (user === undefined) {
|
if (!isUser(user)) {
|
||||||
user = (await guild.client.users.fetch(userId)) as User;
|
info.message =
|
||||||
|
'The user does not exist! (The user provided is probably wrong, or their account has been deleted.)';
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets mod's GuildMember
|
// Gets mod's GuildMember
|
||||||
const mod = guild.members.cache.get(modId);
|
const mod = await getGuildMember(modId, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (mod === undefined) {
|
if (!isGuildMember(mod)) {
|
||||||
info.message = 'Error fetching mod!';
|
info.message = 'Error fetching mod!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -225,13 +235,9 @@ export class TempBanCommand extends Command {
|
|||||||
await updateUser(mod);
|
await updateUser(mod);
|
||||||
|
|
||||||
// Gets guildMember
|
// Gets guildMember
|
||||||
let member = guild.members.cache.get(userId);
|
const member = await getGuildMember(userId, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (isGuildMember(member)) {
|
||||||
member = await guild.members.fetch(userId).catch(() => undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (member !== undefined) {
|
|
||||||
// Checks if the user is not restricted
|
// Checks if the user is not restricted
|
||||||
if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
||||||
info.message = 'You need to restrict the user first!';
|
info.message = 'You need to restrict the user first!';
|
||||||
@@ -258,11 +264,13 @@ 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(
|
await this.container.tasks.create(
|
||||||
'tempBan',
|
|
||||||
{
|
{
|
||||||
userId: user.id,
|
name: 'tempBan',
|
||||||
guildId: guild.id,
|
payload: {
|
||||||
|
userId: user.id,
|
||||||
|
guildId: guild.id,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
time.offset,
|
time.offset,
|
||||||
);
|
);
|
||||||
@@ -271,23 +279,25 @@ export class TempBanCommand extends Command {
|
|||||||
info.success = true;
|
info.success = true;
|
||||||
|
|
||||||
// Log the ban
|
// Log the ban
|
||||||
let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.restricted);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (logChannel === undefined) {
|
if (!isTextBasedChannel(logChannel)) {
|
||||||
logChannel = (await guild.channels.fetch(
|
this.container.logger.error('Temp Ban: Could not fetch log channel');
|
||||||
IDs.channels.logs.restricted,
|
|
||||||
)) as TextChannel | undefined;
|
info.message =
|
||||||
if (logChannel === undefined) {
|
`${user} has been temporarily banned for ${banLength}. ` +
|
||||||
this.container.logger.error(
|
"This hasn't been logged in a text channel as log channel could not be found";
|
||||||
'Temp Ban Error: Could not fetch log channel',
|
|
||||||
);
|
return info;
|
||||||
info.message =
|
} else if (!logChannel.isSendable()) {
|
||||||
`${user} has been temporarily banned for ${banLength}. ` +
|
this.container.logger.error(
|
||||||
"This hasn't been logged in a text channel as log channel could not be found";
|
'Temp Ban: The bot does not have permission to send in the logs channel!',
|
||||||
return info;
|
);
|
||||||
}
|
info.message =
|
||||||
|
`${user} has been temporarily banned for ${banLength}. ` +
|
||||||
|
"This hasn't been logged in a text channel as the bot does not have permission to send logs!";
|
||||||
|
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const log = new EmbedBuilder()
|
const log = new EmbedBuilder()
|
||||||
|
|||||||
@@ -18,22 +18,31 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type {
|
import {
|
||||||
User,
|
User,
|
||||||
Message,
|
Message,
|
||||||
Snowflake,
|
Snowflake,
|
||||||
TextChannel,
|
|
||||||
Guild,
|
Guild,
|
||||||
GuildBan,
|
GuildBan,
|
||||||
|
MessageFlagsBitField,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { removeBan, checkBan, addBan } from '#utils/database/ban';
|
import { removeBan, checkBan, addBan } from '#utils/database/moderation/ban';
|
||||||
import { checkTempBan, removeTempBan } from '#utils/database/tempBan';
|
import {
|
||||||
|
checkTempBan,
|
||||||
|
removeTempBan,
|
||||||
|
} from '#utils/database/moderation/tempBan';
|
||||||
import { addEmptyUser, addExistingUser } from '#utils/database/dbExistingUser';
|
import { addEmptyUser, addExistingUser } from '#utils/database/dbExistingUser';
|
||||||
|
import { getGuildMember, getTextBasedChannel, getUser } from '#utils/fetcher';
|
||||||
|
import {
|
||||||
|
isGuildMember,
|
||||||
|
isTextBasedChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
import { isNullish } from '@sapphire/utilities';
|
||||||
|
|
||||||
export class UnbanCommand extends Command {
|
export class UnbanCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'unban',
|
name: 'unban',
|
||||||
@@ -72,8 +81,8 @@ export class UnbanCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -120,10 +129,10 @@ export class UnbanCommand extends Command {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Gets mod's GuildMember
|
// Gets mod's GuildMember
|
||||||
const mod = guild.members.cache.get(modId);
|
const mod = await getGuildMember(modId, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (mod === undefined) {
|
if (!isGuildMember(mod)) {
|
||||||
info.message = 'Error fetching mod!';
|
info.message = 'Error fetching mod!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -131,14 +140,11 @@ export class UnbanCommand extends Command {
|
|||||||
// Check if mod is in database
|
// Check if mod is in database
|
||||||
await addExistingUser(mod);
|
await addExistingUser(mod);
|
||||||
|
|
||||||
let user = guild.client.users.cache.get(userId);
|
const user = await getUser(userId);
|
||||||
|
|
||||||
if (user === undefined) {
|
if (user === undefined) {
|
||||||
user = await guild.client.users.fetch(userId);
|
info.message = 'Could not fetch the user!';
|
||||||
if (user === undefined) {
|
return info;
|
||||||
info.message = 'Could not fetch the user!';
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let dbBan = await checkBan(userId);
|
let dbBan = await checkBan(userId);
|
||||||
@@ -158,7 +164,7 @@ export class UnbanCommand extends Command {
|
|||||||
}
|
}
|
||||||
let { reason } = ban;
|
let { reason } = ban;
|
||||||
|
|
||||||
if (reason === null || reason === undefined) {
|
if (isNullish(reason)) {
|
||||||
reason = '';
|
reason = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,19 +194,21 @@ export class UnbanCommand extends Command {
|
|||||||
info.success = true;
|
info.success = true;
|
||||||
|
|
||||||
// Log unban
|
// Log unban
|
||||||
let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
|
let logChannel = await getTextBasedChannel(IDs.channels.logs.restricted);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (logChannel === undefined) {
|
if (!isTextBasedChannel(logChannel)) {
|
||||||
logChannel = (await guild.channels.fetch(
|
this.container.logger.error('Unban Error: Could not fetch log channel');
|
||||||
IDs.channels.logs.restricted,
|
info.message = `${user} has been unbanned. This hasn't been logged in a text channel as log channel could not be found`;
|
||||||
)) as TextChannel | undefined;
|
|
||||||
if (logChannel === undefined) {
|
return info;
|
||||||
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`;
|
if (!logChannel.isSendable()) {
|
||||||
return info;
|
this.container.logger.error(
|
||||||
}
|
'Unban: The bot does not have permission to send in the logs channel!',
|
||||||
|
);
|
||||||
|
info.message = `${user} has been unbanned. This hasn't been logged in a text channel as the bot does not have permission to send logs!`;
|
||||||
|
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const log = new EmbedBuilder()
|
const log = new EmbedBuilder()
|
||||||
|
|||||||
@@ -22,16 +22,26 @@
|
|||||||
import { Args, container, RegisterBehavior } from '@sapphire/framework';
|
import { Args, container, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { Subcommand } from '@sapphire/plugin-subcommands';
|
import { Subcommand } from '@sapphire/plugin-subcommands';
|
||||||
import {
|
import {
|
||||||
ChannelType,
|
|
||||||
GuildMember,
|
GuildMember,
|
||||||
Message,
|
Message,
|
||||||
|
MessageFlagsBitField,
|
||||||
PermissionsBitField,
|
PermissionsBitField,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import type { TextChannel, Snowflake } from 'discord.js';
|
import type { Snowflake } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getGuildMember, getRole, getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import {
|
||||||
|
isGuildMember,
|
||||||
|
isTextChannel,
|
||||||
|
isThreadChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class DiversityCommand extends Subcommand {
|
export class DiversityCommand extends Subcommand {
|
||||||
public constructor(context: Subcommand.Context, options: Subcommand.Options) {
|
public constructor(
|
||||||
|
context: Subcommand.LoaderContext,
|
||||||
|
options: Subcommand.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'diversity',
|
name: 'diversity',
|
||||||
@@ -86,47 +96,25 @@ export class DiversityCommand extends Subcommand {
|
|||||||
|
|
||||||
// Command run
|
// Command run
|
||||||
public async toggleOpen(interaction: Subcommand.ChatInputCommandInteraction) {
|
public async toggleOpen(interaction: Subcommand.ChatInputCommandInteraction) {
|
||||||
// Check if guild is not null
|
|
||||||
if (interaction.guild === null) {
|
|
||||||
await interaction.reply({
|
|
||||||
content: 'Guild not found!',
|
|
||||||
ephemeral: true,
|
|
||||||
fetchReply: true,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the channel
|
// Get the channel
|
||||||
const channel = interaction.guild.channels.cache.get(interaction.channelId);
|
const channel = await getTextBasedChannel(interaction.channelId);
|
||||||
// Check if channel is not undefined
|
|
||||||
if (channel === undefined) {
|
|
||||||
await interaction.reply({
|
|
||||||
content: 'Channel not found!',
|
|
||||||
ephemeral: true,
|
|
||||||
fetchReply: true,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if channel is text
|
// Check if channel is text
|
||||||
if (channel.type !== ChannelType.GuildText) {
|
if (!isTextChannel(channel)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Channel is not a text channel!',
|
content: 'Channel is not a text channel!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts GuildBasedChannel to TextChannel
|
|
||||||
const channelText = channel as TextChannel;
|
|
||||||
|
|
||||||
// Check if the command was run in the diversity section
|
// Check if the command was run in the diversity section
|
||||||
if (channel.parentId !== IDs.categories.diversity) {
|
if (channel.parentId !== IDs.categories.diversity) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Command was not run in the Diversity section!',
|
content: 'Command was not run in the Diversity section!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -137,13 +125,13 @@ export class DiversityCommand extends Subcommand {
|
|||||||
.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, {
|
await channel.permissionOverwrites.edit(IDs.roles.vegan.vegan, {
|
||||||
SendMessages: !open,
|
SendMessages: !open,
|
||||||
});
|
});
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `${!open ? 'Opened' : 'Closed'} this channel.`,
|
content: `${!open ? 'Opened' : 'Closed'} this channel.`,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,51 +140,69 @@ export class DiversityCommand extends Subcommand {
|
|||||||
) {
|
) {
|
||||||
// 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', true);
|
||||||
const mod = interaction.member;
|
const mod = interaction.member;
|
||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (user === null || guild === null || mod === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching user!',
|
content: 'Error fetching the guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets guildMember whilst removing the ability of each other variables being null
|
if (!isGuildMember(mod)) {
|
||||||
const guildMember = guild.members.cache.get(user.id);
|
|
||||||
const diversity = guild.roles.cache.get(IDs.roles.staff.diversity);
|
|
||||||
|
|
||||||
// Checks if guildMember is null
|
|
||||||
if (guildMember === undefined || diversity === undefined) {
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching user!',
|
content: 'Error fetching your user!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
const diversity = await getRole(IDs.roles.staff.diversity, guild);
|
||||||
|
|
||||||
|
// Checks if the member was found
|
||||||
|
if (!isGuildMember(member)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Error fetching the user!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
withResponse: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the role was found
|
||||||
|
if (!isRole(diversity)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Error fetching the diversity role!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if the user has Diversity and to give them or remove them based on if they have it
|
// Checks if the user has Diversity and to give them or remove them based on if they have it
|
||||||
if (guildMember.roles.cache.has(IDs.roles.staff.diversity)) {
|
if (member.roles.cache.has(IDs.roles.staff.diversity)) {
|
||||||
// Remove the Diversity role from the user
|
// Remove the Diversity role from the user
|
||||||
await guildMember.roles.remove(diversity);
|
await member.roles.remove(diversity);
|
||||||
await this.threadManager(guildMember.id, false);
|
await this.threadManager(member.id, false);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Removed the ${diversity.name} role from ${user}`,
|
content: `Removed the ${diversity.name} role from ${user}`,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Add Diversity Team role to the user
|
// Add Diversity Team role to the user
|
||||||
await guildMember.roles.add(diversity);
|
await member.roles.add(diversity);
|
||||||
await this.threadManager(guildMember.id, true);
|
await this.threadManager(member.id, true);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Gave ${user} the ${diversity.name} role!`,
|
content: `Gave ${user} the ${diversity.name} role!`,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
await user
|
await user
|
||||||
.send(`You have been given the ${diversity.name} role by ${mod}!`)
|
.send(`You have been given the ${diversity.name} role by ${mod}!`)
|
||||||
@@ -216,7 +222,7 @@ export class DiversityCommand extends Subcommand {
|
|||||||
|
|
||||||
const mod = message.member;
|
const mod = message.member;
|
||||||
|
|
||||||
if (mod === null) {
|
if (!isGuildMember(mod)) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply(
|
await message.reply(
|
||||||
'Diversity coordinator not found! Try again or contact a developer!',
|
'Diversity coordinator not found! Try again or contact a developer!',
|
||||||
@@ -232,9 +238,9 @@ export class DiversityCommand extends Subcommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const diversity = guild.roles.cache.get(IDs.roles.staff.diversity);
|
const diversity = await getRole(IDs.roles.staff.diversity, guild);
|
||||||
|
|
||||||
if (diversity === undefined) {
|
if (!isRole(diversity)) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply('Role not found! Try again or contact a developer!');
|
await message.reply('Role not found! Try again or contact a developer!');
|
||||||
return;
|
return;
|
||||||
@@ -267,11 +273,8 @@ export class DiversityCommand extends Subcommand {
|
|||||||
const thread = await container.client.channels.fetch(
|
const thread = await container.client.channels.fetch(
|
||||||
IDs.channels.diversity.diversity,
|
IDs.channels.diversity.diversity,
|
||||||
);
|
);
|
||||||
if (thread === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!thread.isThread()) {
|
if (!isThreadChannel(thread)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Message } from 'discord.js';
|
import { Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import { ChannelType } from 'discord.js';
|
import { ChannelType } from 'discord.js';
|
||||||
|
import {
|
||||||
|
isGuildMember,
|
||||||
|
isVoiceBasedChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
import { getVoiceBasedChannel } from '#utils/fetcher';
|
||||||
|
|
||||||
export class MoveAllCommand extends Command {
|
export class MoveAllCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'moveall',
|
name: 'moveall',
|
||||||
@@ -61,7 +66,9 @@ export class MoveAllCommand extends Command {
|
|||||||
const { member } = interaction;
|
const { member } = interaction;
|
||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
channel.type !== ChannelType.GuildVoice &&
|
channel.type !== ChannelType.GuildVoice &&
|
||||||
@@ -81,40 +88,31 @@ export class MoveAllCommand extends Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (member === null) {
|
if (!isGuildMember(member)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'Error fetching your user',
|
content: 'Error fetching your user',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = guild.members.cache.get(member.user.id);
|
if (member.voice.channelId === null) {
|
||||||
|
|
||||||
if (mod === undefined) {
|
|
||||||
await interaction.editReply({
|
|
||||||
content: 'Error fetching user from guild',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mod.voice.channelId === null) {
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'You need to be in a voice channel to run this command!',
|
content: 'You need to be in a voice channel to run this command!',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const voice = guild.channels.cache.get(mod.voice.channelId);
|
const voice = await getVoiceBasedChannel(member.voice.channelId);
|
||||||
|
|
||||||
if (voice === undefined || !voice.isVoiceBased()) {
|
if (!isVoiceBasedChannel(voice)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'Error fetching your current voice channel!',
|
content: 'Error fetching your current voice channel!',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
voice.members.forEach((memberVC) => {
|
voice.members.forEach((vcMember) => {
|
||||||
memberVC.voice.setChannel(channel.id);
|
vcMember.voice.setChannel(channel.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
@@ -135,7 +133,7 @@ export class MoveAllCommand extends Command {
|
|||||||
const mod = message.member;
|
const mod = message.member;
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (mod === null) {
|
if (!isGuildMember(mod)) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply('Could not find your user!');
|
await message.reply('Could not find your user!');
|
||||||
return;
|
return;
|
||||||
@@ -155,9 +153,9 @@ export class MoveAllCommand extends Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const voice = guild.channels.cache.get(mod.voice.channelId);
|
const voice = await getVoiceBasedChannel(mod.voice.channelId);
|
||||||
|
|
||||||
if (voice === undefined || !voice.isVoiceBased()) {
|
if (!isVoiceBasedChannel(voice)) {
|
||||||
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;
|
||||||
|
|||||||
@@ -18,10 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { GuildMember, Message } from 'discord.js';
|
import { GuildMember, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
|
import { getGuildMember } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class RenameUserCommand extends Command {
|
export class RenameUserCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'rename',
|
name: 'rename',
|
||||||
@@ -68,21 +70,21 @@ export class RenameUserCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets guildMember whilst removing the ability of each other variables being null
|
// Gets guildMember whilst removing the ability of each other variables being null
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching user!',
|
content: 'Error fetching user!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -93,15 +95,15 @@ export class RenameUserCommand extends Command {
|
|||||||
} 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,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Changed ${user}'s nickname`,
|
content: `Changed ${user}'s nickname`,
|
||||||
fetchReply: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
ephemeral: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
ChannelType,
|
ChannelType,
|
||||||
EmbedBuilder,
|
EmbedBuilder,
|
||||||
|
MessageFlagsBitField,
|
||||||
PermissionsBitField,
|
PermissionsBitField,
|
||||||
time,
|
time,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
@@ -36,9 +37,14 @@ import {
|
|||||||
updateUser,
|
updateUser,
|
||||||
fetchRoles,
|
fetchRoles,
|
||||||
} from '#utils/database/dbExistingUser';
|
} from '#utils/database/dbExistingUser';
|
||||||
import { restrict, checkActive } from '#utils/database/restriction';
|
import { restrict, checkActive } from '#utils/database/moderation/restriction';
|
||||||
import { randint } from '#utils/maths';
|
import { randint } from '#utils/maths';
|
||||||
import { blockedRolesAfterRestricted } from '#utils/blockedRoles';
|
import { blockedRolesAfterRestricted } from '#utils/blockedRoles';
|
||||||
|
import { getGuildMember, getTextBasedChannel, getUser } from '#utils/fetcher';
|
||||||
|
import {
|
||||||
|
isGuildMember,
|
||||||
|
isTextBasedChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export async function restrictRun(
|
export async function restrictRun(
|
||||||
userId: Snowflake,
|
userId: Snowflake,
|
||||||
@@ -52,21 +58,18 @@ export async function restrictRun(
|
|||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = guild.client.users.cache.get(userId);
|
const user = await getUser(userId);
|
||||||
|
|
||||||
if (user === undefined) {
|
if (user === undefined) {
|
||||||
user = await guild.client.users.fetch(userId);
|
info.message = 'Error fetching user';
|
||||||
if (user === undefined) {
|
return info;
|
||||||
info.message = 'Error fetching user';
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets mod's GuildMember
|
// Gets mod's GuildMember
|
||||||
const mod = guild.members.cache.get(modId);
|
const mod = await getGuildMember(modId, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (mod === undefined) {
|
if (!isGuildMember(mod)) {
|
||||||
info.message = 'Error fetching mod';
|
info.message = 'Error fetching mod';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -80,17 +83,13 @@ export async function restrictRun(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gets guildMember
|
// Gets guildMember
|
||||||
let member = guild.members.cache.get(userId);
|
const member = await getGuildMember(userId, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
|
||||||
member = await guild.members.fetch(userId).catch(() => undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
const restrictRoles = IDs.roles.restrictions.restricted;
|
const restrictRoles = IDs.roles.restrictions.restricted;
|
||||||
|
|
||||||
let section = tolerance ? randint(3, 4) : randint(1, 2);
|
let section = tolerance ? randint(3, 4) : randint(1, 2);
|
||||||
|
|
||||||
if (member !== undefined) {
|
if (isGuildMember(member)) {
|
||||||
// Checks if the user is not restricted
|
// Checks if the user is not restricted
|
||||||
if (member.roles.cache.hasAny(...restrictRoles)) {
|
if (member.roles.cache.hasAny(...restrictRoles)) {
|
||||||
info.message = `${member} is already restricted!`;
|
info.message = `${member} is already restricted!`;
|
||||||
@@ -218,7 +217,7 @@ export async function restrictRun(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (member !== undefined && member.voice.channelId !== null) {
|
if (isGuildMember(member) && member.voice.channelId !== null) {
|
||||||
await member.voice.disconnect();
|
await member.voice.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,19 +241,20 @@ export async function restrictRun(
|
|||||||
await user.send({ embeds: [dmEmbed] }).catch(() => {});
|
await user.send({ embeds: [dmEmbed] }).catch(() => {});
|
||||||
|
|
||||||
// Log the ban
|
// Log the ban
|
||||||
let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.restricted);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (logChannel === undefined) {
|
if (!isTextBasedChannel(logChannel)) {
|
||||||
logChannel = (await guild.channels.fetch(IDs.channels.logs.restricted)) as
|
container.logger.error('Restrict: Could not fetch log channel');
|
||||||
| TextChannel
|
info.message = `Restricted ${user} but could not find the log channel. This has been logged to the database.`;
|
||||||
| undefined;
|
|
||||||
if (logChannel === undefined) {
|
return info;
|
||||||
container.logger.error('Restrict Error: Could not fetch log channel');
|
} else if (!logChannel.isSendable()) {
|
||||||
info.message = `Restricted ${user} but could not find the log channel. This has been logged to the database.`;
|
container.logger.error(
|
||||||
return info;
|
'Restrict: The bot does not have permission to send in the logs channel!',
|
||||||
}
|
);
|
||||||
|
info.message = `${user} has been restricted. This hasn't been logged in a text channel as the bot does not have permission to send logs!`;
|
||||||
|
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = new EmbedBuilder()
|
const message = new EmbedBuilder()
|
||||||
@@ -277,7 +277,7 @@ export async function restrictRun(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RestrictCommand extends Command {
|
export class RestrictCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'restrict',
|
name: 'restrict',
|
||||||
@@ -324,15 +324,17 @@ export class RestrictCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await restrictRun(user?.id, mod.id, reason, guild);
|
const info = await restrictRun(user.id, mod.id, reason, guild);
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: info.message,
|
content: info.message,
|
||||||
@@ -367,7 +369,7 @@ export class RestrictCommand extends Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const info = await restrictRun(user?.id, mod.id, reason, guild);
|
const info = await restrictRun(user.id, mod.id, reason, guild);
|
||||||
|
|
||||||
await message.reply(info.message);
|
await message.reply(info.message);
|
||||||
await message.react(info.success ? '✅' : '❌');
|
await message.react(info.success ? '✅' : '❌');
|
||||||
|
|||||||
@@ -18,18 +18,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { ChannelType, EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import type { Message, TextChannel, Guild, Snowflake } from 'discord.js';
|
import type { Message, 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/moderation/restriction';
|
||||||
import { checkStaff } from '#utils/checker';
|
import { checkStaff } from '#utils/checker';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
import { isGuildMember, isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
import { getGuildMember, getUser } from '#utils/fetcher';
|
||||||
|
|
||||||
export class RestrictLogsCommand extends Command {
|
export class RestrictLogsCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'restrictlogs',
|
name: 'restrictlogs',
|
||||||
description: 'Unrestricts a user',
|
description: 'Shows restriction history for a user',
|
||||||
preconditions: ['ModOnly'],
|
preconditions: ['ModOnly'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -56,48 +59,48 @@ export class RestrictLogsCommand extends Command {
|
|||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
// Get the arguments
|
// Get the arguments
|
||||||
const user = interaction.options.getUser('user');
|
const user = interaction.options.getUser('user');
|
||||||
let { channel } = interaction;
|
const { channel } = interaction;
|
||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (guild === null || channel === null) {
|
if (guild === null || channel === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild or channel!',
|
content: 'Error fetching guild or channel!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let userId: Snowflake | null = null;
|
let userId: Snowflake | null = null;
|
||||||
|
|
||||||
if (user !== undefined && user !== null) {
|
if (isUser(user)) {
|
||||||
userId = user.id;
|
userId = user.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
let staffChannel = false;
|
const staffChannel = checkStaff(channel);
|
||||||
if (channel.type === ChannelType.GuildText) {
|
if (staffChannel) {
|
||||||
channel = channel as TextChannel;
|
// Checking Channel topic for Snowflake
|
||||||
staffChannel = checkStaff(channel);
|
|
||||||
|
|
||||||
if (userId === null) {
|
if (userId === null) {
|
||||||
let topic: string[];
|
let topic: string[];
|
||||||
|
|
||||||
if (channel.parentId === IDs.categories.modMail) {
|
if (
|
||||||
|
isTextChannel(channel) &&
|
||||||
|
channel.parentId === IDs.categories.modMail &&
|
||||||
|
channel.topic !== null
|
||||||
|
) {
|
||||||
// Checks if the channel topic has the user's snowflake
|
// Checks if the channel topic has the user's snowflake
|
||||||
if (channel.topic !== null) {
|
topic = channel.topic.split(' ');
|
||||||
topic = channel.topic.split(' ');
|
userId = topic[2];
|
||||||
// eslint-disable-next-line prefer-destructuring
|
|
||||||
userId = topic[2];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no Snowflake was provided/found
|
||||||
if (userId === null) {
|
if (userId === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'User could not be found or was not provided!',
|
content: 'User could not be found or was not provided!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -107,8 +110,8 @@ export class RestrictLogsCommand extends Command {
|
|||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
embeds: info.embeds,
|
embeds: info.embeds,
|
||||||
content: info.message,
|
content: info.message,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
ephemeral: !staffChannel,
|
flags: staffChannel ? undefined : MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,10 +135,11 @@ export class RestrictLogsCommand extends Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempting to get the user's Snowflake from the channel topic.
|
||||||
if (userId === null) {
|
if (userId === null) {
|
||||||
const { channel } = message;
|
const { channel } = message;
|
||||||
|
|
||||||
if (channel.type !== ChannelType.GuildText) {
|
if (!isTextChannel(channel)) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply('User was not provided!');
|
await message.reply('User was not provided!');
|
||||||
return;
|
return;
|
||||||
@@ -143,13 +147,13 @@ export class RestrictLogsCommand extends Command {
|
|||||||
|
|
||||||
let topic: string[];
|
let topic: string[];
|
||||||
|
|
||||||
if (channel.parentId === IDs.categories.modMail) {
|
// Checks if the channel topic has the user's snowflake
|
||||||
// Checks if the channel topic has the user's snowflake
|
if (
|
||||||
if (channel.topic !== null) {
|
channel.parentId === IDs.categories.modMail &&
|
||||||
topic = channel.topic.split(' ');
|
channel.topic !== null
|
||||||
// eslint-disable-next-line prefer-destructuring
|
) {
|
||||||
userId = topic[2];
|
topic = channel.topic.split(' ');
|
||||||
}
|
userId = topic[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,14 +178,12 @@ export class RestrictLogsCommand extends Command {
|
|||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = guild.client.users.cache.get(userId);
|
const user = await getUser(userId);
|
||||||
|
|
||||||
if (user === undefined) {
|
if (!isUser(user)) {
|
||||||
user = await guild.client.users.fetch(userId);
|
info.message =
|
||||||
if (user === undefined) {
|
'Error fetching user. (You probably provided an incorrect user.)';
|
||||||
info.message = 'Error fetching user';
|
return info;
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const restrictions = await getRestrictions(userId);
|
const restrictions = await getRestrictions(userId);
|
||||||
@@ -206,14 +208,15 @@ export class RestrictLogsCommand extends Command {
|
|||||||
) {
|
) {
|
||||||
// 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 = await getGuildMember(restMod, guild);
|
||||||
if (restModMember !== undefined) {
|
if (isGuildMember(restModMember)) {
|
||||||
restMod = restModMember.displayName;
|
restMod = restModMember.displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
let endRestMod = restrictions[i].endModId;
|
let endRestMod = restrictions[i].endModId;
|
||||||
if (endRestMod !== null) {
|
if (endRestMod !== null) {
|
||||||
const endRestModMember = guild.members.cache.get(endRestMod);
|
const endRestModMember = await getGuildMember(endRestMod, guild);
|
||||||
if (endRestModMember !== undefined) {
|
if (isGuildMember(endRestModMember)) {
|
||||||
endRestMod = endRestModMember.displayName;
|
endRestMod = endRestModMember.displayName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { User, Message } from 'discord.js';
|
import { User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import { restrictRun } from './restrict';
|
import { restrictRun } from './restrict';
|
||||||
|
|
||||||
export class RestrictToleranceCommand extends Command {
|
export class RestrictToleranceCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'restricttolerance',
|
name: 'restricttolerance',
|
||||||
@@ -69,15 +69,17 @@ export class RestrictToleranceCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await restrictRun(user?.id, mod.id, reason, guild, true);
|
const info = await restrictRun(user.id, mod.id, reason, guild, true);
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: info.message,
|
content: info.message,
|
||||||
@@ -112,7 +114,7 @@ export class RestrictToleranceCommand extends Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const info = await restrictRun(user?.id, mod.id, reason, guild, true);
|
const info = await restrictRun(user.id, mod.id, reason, guild, true);
|
||||||
|
|
||||||
await message.reply(info.message);
|
await message.reply(info.message);
|
||||||
await message.react(info.success ? '✅' : '❌');
|
await message.react(info.success ? '✅' : '❌');
|
||||||
|
|||||||
@@ -19,12 +19,21 @@
|
|||||||
|
|
||||||
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 { MessageFlagsBitField } from 'discord.js';
|
||||||
import { CategoryChannel, ChannelType } from 'discord.js';
|
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
import {
|
||||||
|
isCategoryChannel,
|
||||||
|
isTextChannel,
|
||||||
|
isVoiceChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
import { getCategoryChannel, getVoiceChannel } from '#utils/fetcher';
|
||||||
|
|
||||||
export class RestrictToolsCommand extends Subcommand {
|
export class RestrictToolsCommand extends Subcommand {
|
||||||
public constructor(context: Subcommand.Context, options: Subcommand.Options) {
|
public constructor(
|
||||||
|
context: Subcommand.LoaderContext,
|
||||||
|
options: Subcommand.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'restricttools',
|
name: 'restricttools',
|
||||||
@@ -75,7 +84,9 @@ export class RestrictToolsCommand extends Subcommand {
|
|||||||
const user = interaction.options.getUser('user');
|
const user = interaction.options.getUser('user');
|
||||||
const { guild, channel } = interaction;
|
const { guild, channel } = interaction;
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (guild === null || channel === null) {
|
if (guild === null || channel === null) {
|
||||||
@@ -87,8 +98,8 @@ export class RestrictToolsCommand extends Subcommand {
|
|||||||
|
|
||||||
let topic: string[];
|
let topic: string[];
|
||||||
|
|
||||||
if (user === null) {
|
if (!isUser(user)) {
|
||||||
if (channel.type !== ChannelType.GuildText) {
|
if (!isTextChannel(channel)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content:
|
content:
|
||||||
'Please make sure you ran this command in the original restricted text channel!',
|
'Please make sure you ran this command in the original restricted text channel!',
|
||||||
@@ -127,10 +138,10 @@ export class RestrictToolsCommand extends Subcommand {
|
|||||||
await channel.delete();
|
await channel.delete();
|
||||||
|
|
||||||
const vcId = topic[3];
|
const vcId = topic[3];
|
||||||
const voiceChannel = guild.channels.cache.get(vcId);
|
const voiceChannel = await getVoiceChannel(vcId);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
voiceChannel !== undefined &&
|
isVoiceChannel(voiceChannel) &&
|
||||||
voiceChannel.parentId === IDs.categories.restricted
|
voiceChannel.parentId === IDs.categories.restricted
|
||||||
) {
|
) {
|
||||||
await voiceChannel.delete();
|
await voiceChannel.delete();
|
||||||
@@ -139,37 +150,47 @@ export class RestrictToolsCommand extends Subcommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const category = guild.channels.cache.get(IDs.categories.restricted) as
|
const category = await getCategoryChannel(IDs.categories.restricted);
|
||||||
| CategoryChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (category === undefined) {
|
if (!isCategoryChannel(category)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'Could not find category!',
|
content: 'Could not find category!',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const textChannels = category.children.cache.filter(
|
const textChannels = category.children.cache.filter((channel) =>
|
||||||
(c) => c.type === ChannelType.GuildText,
|
isTextChannel(channel),
|
||||||
);
|
);
|
||||||
textChannels.forEach((c) => {
|
|
||||||
const textChannel = c as TextChannel;
|
for (const c of textChannels) {
|
||||||
|
const channel = c[1];
|
||||||
|
|
||||||
|
// Checks that the channel is a text channel
|
||||||
|
if (!isTextChannel(channel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks that the channel has a topic
|
||||||
|
if (channel.topic === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 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?.id)) {
|
if (channel.topic.includes(user.id)) {
|
||||||
topic = textChannel.topic.split(' ');
|
topic = channel.topic.split(' ');
|
||||||
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 = await getVoiceChannel(vcId);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
voiceChannel !== undefined &&
|
isVoiceChannel(voiceChannel) &&
|
||||||
voiceChannel.parentId === IDs.categories.restricted
|
voiceChannel.parentId === IDs.categories.restricted
|
||||||
) {
|
) {
|
||||||
voiceChannel.delete();
|
await voiceChannel.delete();
|
||||||
}
|
}
|
||||||
textChannel.delete();
|
await channel.delete();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `Successfully deleted the channel for ${user}`,
|
content: `Successfully deleted the channel for ${user}`,
|
||||||
|
|||||||
@@ -18,18 +18,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import { CategoryChannel, ChannelType, EmbedBuilder } from 'discord.js';
|
import type { Guild, Message, Snowflake, User } from 'discord.js';
|
||||||
import type { User, Message, TextChannel, Guild, Snowflake } from 'discord.js';
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { fetchRoles, addExistingUser } from '#utils/database/dbExistingUser';
|
import { addExistingUser, fetchRoles } from '#utils/database/dbExistingUser';
|
||||||
import {
|
import {
|
||||||
unRestrict,
|
|
||||||
checkActive,
|
checkActive,
|
||||||
|
unRestrict,
|
||||||
unRestrictLegacy,
|
unRestrictLegacy,
|
||||||
} from '#utils/database/restriction';
|
} from '#utils/database/moderation/restriction';
|
||||||
|
import {
|
||||||
|
getCategoryChannel,
|
||||||
|
getGuildMember,
|
||||||
|
getTextBasedChannel,
|
||||||
|
getUser,
|
||||||
|
getVoiceChannel,
|
||||||
|
} from '#utils/fetcher';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
import {
|
||||||
|
isCategoryChannel,
|
||||||
|
isGuildMember,
|
||||||
|
isTextBasedChannel,
|
||||||
|
isTextChannel,
|
||||||
|
isVoiceChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class UnRestrictCommand extends Command {
|
export class UnRestrictCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'unrestrict',
|
name: 'unrestrict',
|
||||||
@@ -69,14 +84,14 @@ export class UnRestrictCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
|
||||||
const info = await this.unRestrictRun(user?.id, mod.id, guild);
|
const info = await this.unRestrictRun(user.id, mod.id, guild);
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: info.message,
|
content: info.message,
|
||||||
@@ -108,7 +123,7 @@ export class UnRestrictCommand extends Command {
|
|||||||
const channelRun = message.channel;
|
const channelRun = message.channel;
|
||||||
|
|
||||||
const info = await this.unRestrictRun(
|
const info = await this.unRestrictRun(
|
||||||
user?.id,
|
user.id,
|
||||||
mod.id,
|
mod.id,
|
||||||
guild,
|
guild,
|
||||||
channelRun.id,
|
channelRun.id,
|
||||||
@@ -132,21 +147,18 @@ export class UnRestrictCommand extends Command {
|
|||||||
runInVeganRestrict: false,
|
runInVeganRestrict: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = guild.client.users.cache.get(userId);
|
const user = await getUser(userId);
|
||||||
|
|
||||||
if (user === undefined) {
|
if (!isUser(user)) {
|
||||||
user = await guild.client.users.fetch(userId);
|
info.message = 'Error fetching user';
|
||||||
if (user === undefined) {
|
return info;
|
||||||
info.message = 'Error fetching user';
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets mod's GuildMember
|
// Gets mod's GuildMember
|
||||||
const mod = guild.members.cache.get(modId);
|
const mod = await getGuildMember(modId, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (mod === undefined) {
|
if (!isGuildMember(mod)) {
|
||||||
info.message = 'Error fetching mod';
|
info.message = 'Error fetching mod';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -155,13 +167,9 @@ export class UnRestrictCommand extends Command {
|
|||||||
await addExistingUser(mod);
|
await addExistingUser(mod);
|
||||||
|
|
||||||
// Gets guildMember
|
// Gets guildMember
|
||||||
let member = guild.members.cache.get(userId);
|
const member = await getGuildMember(userId, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
member = await guild.members.fetch(userId).catch(() => 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;
|
||||||
}
|
}
|
||||||
@@ -180,16 +188,20 @@ export class UnRestrictCommand extends Command {
|
|||||||
if (await checkActive(userId)) {
|
if (await checkActive(userId)) {
|
||||||
const roles = await fetchRoles(userId);
|
const roles = await fetchRoles(userId);
|
||||||
await member.roles.add(roles);
|
await member.roles.add(roles);
|
||||||
|
|
||||||
// Unrestricts the user on the database
|
// Unrestricts the user on the database
|
||||||
await unRestrict(userId, modId);
|
await unRestrict(userId, modId);
|
||||||
} else {
|
} else {
|
||||||
let section = 1;
|
let section = 1;
|
||||||
|
|
||||||
for (let i = 0; i < restrictRoles.length; i += 1) {
|
for (let i = 0; i < restrictRoles.length; i += 1) {
|
||||||
if (member.roles.cache.has(restrictRoles[i])) {
|
if (member.roles.cache.has(restrictRoles[i])) {
|
||||||
section = i + 1;
|
section = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await member.roles.add(IDs.roles.nonvegan.nonvegan);
|
await member.roles.add(IDs.roles.nonvegan.nonvegan);
|
||||||
|
|
||||||
// Unrestricts the user on the database but for restricts done on the old bot
|
// Unrestricts the user on the database but for restricts done on the old bot
|
||||||
await unRestrictLegacy(userId, modId, section);
|
await unRestrictLegacy(userId, modId, section);
|
||||||
}
|
}
|
||||||
@@ -198,57 +210,73 @@ 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.get(IDs.categories.restricted) as
|
const category = await getCategoryChannel(IDs.categories.restricted);
|
||||||
| CategoryChannel
|
|
||||||
| undefined;
|
if (!isCategoryChannel(category)) {
|
||||||
|
info.message =
|
||||||
|
'Could not find the restricted category! The channels will have to be deleted manually.';
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
let topic: string[];
|
let topic: string[];
|
||||||
|
|
||||||
if (category !== undefined) {
|
const textChannels = category.children.cache.filter((channel) =>
|
||||||
const textChannels = category.children.cache.filter(
|
isTextChannel(channel),
|
||||||
(c) => c.type === ChannelType.GuildText,
|
);
|
||||||
);
|
|
||||||
textChannels.forEach((c) => {
|
|
||||||
const textChannel = c as TextChannel;
|
|
||||||
// Checks if the channel topic has the user's snowflake
|
|
||||||
if (textChannel.topic?.includes(userId)) {
|
|
||||||
if (textChannel.id === channelRun) {
|
|
||||||
info.runInVeganRestrict = true;
|
|
||||||
}
|
|
||||||
topic = textChannel.topic.split(' ');
|
|
||||||
const vcId = topic[topic.indexOf(userId) + 1];
|
|
||||||
const voiceChannel = guild.channels.cache.get(vcId);
|
|
||||||
|
|
||||||
if (
|
for (const c of textChannels) {
|
||||||
voiceChannel !== undefined &&
|
const channel = c[1];
|
||||||
voiceChannel.parentId === IDs.categories.restricted
|
|
||||||
) {
|
// Checks that the channel is a text channel
|
||||||
voiceChannel.delete();
|
if (!isTextChannel(channel)) {
|
||||||
}
|
continue;
|
||||||
textChannel.delete();
|
}
|
||||||
|
|
||||||
|
// Checks that the channel has a topic
|
||||||
|
if (channel.topic === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the channel topic has the user's snowflake
|
||||||
|
if (channel.topic.includes(userId)) {
|
||||||
|
if (channel.id === channelRun) {
|
||||||
|
info.runInVeganRestrict = true;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
topic = channel.topic.split(' ');
|
||||||
|
const vcId = topic[topic.indexOf(user.id) + 1];
|
||||||
|
const voiceChannel = await getVoiceChannel(vcId);
|
||||||
|
|
||||||
|
if (
|
||||||
|
isVoiceChannel(voiceChannel) &&
|
||||||
|
// Used for sanitising the channel topic, so another voice channel does not get deleted
|
||||||
|
voiceChannel.parentId === IDs.categories.restricted
|
||||||
|
) {
|
||||||
|
await voiceChannel.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
await channel.delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info.success = true;
|
info.success = true;
|
||||||
|
|
||||||
// Log the ban
|
// Log the ban
|
||||||
let logChannel = guild.channels.cache.get(IDs.channels.logs.restricted) as
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.restricted);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (logChannel === undefined) {
|
if (!isTextBasedChannel(logChannel)) {
|
||||||
logChannel = (await guild.channels.fetch(
|
this.container.logger.error('Unrestrict: Could not fetch log channel');
|
||||||
IDs.channels.logs.restricted,
|
info.message = `Unrestricted ${user} but could not find the log channel. This has been logged to the database.`;
|
||||||
)) as TextChannel | undefined;
|
|
||||||
if (logChannel === undefined) {
|
return info;
|
||||||
this.container.logger.error(
|
} else if (!logChannel.isSendable()) {
|
||||||
'Restrict Error: Could not fetch log channel',
|
this.container.logger.error(
|
||||||
);
|
'Unrestrict: The bot does not have permission to send in the logs channel!',
|
||||||
info.message = `Unrestricted ${user} but could not find the log channel. This has been logged to the database.`;
|
);
|
||||||
return info;
|
info.message = `Unrestricted ${user} but could not find the log channel. This hasn't been logged in a text channel as the bot does not have permission to send logs!`;
|
||||||
}
|
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = new EmbedBuilder()
|
const message = new EmbedBuilder()
|
||||||
|
|||||||
@@ -18,13 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Message, TextBasedChannel } from 'discord.js';
|
import { Message, MessageFlagsBitField, TextBasedChannel } from 'discord.js';
|
||||||
import { ChannelType } from 'discord.js';
|
|
||||||
import { Duration, DurationFormatter } from '@sapphire/time-utilities';
|
import { Duration, DurationFormatter } from '@sapphire/time-utilities';
|
||||||
import { isNumber } from '#utils/maths';
|
import { isNumber } from '#utils/maths';
|
||||||
|
import {
|
||||||
|
isTextBasedChannel,
|
||||||
|
isTextChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class SlowmodeCommand extends Command {
|
export class SlowmodeCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'slowmode',
|
name: 'slowmode',
|
||||||
@@ -58,11 +61,11 @@ export class SlowmodeCommand extends Command {
|
|||||||
const duration = interaction.options.getString('duration', true);
|
const duration = interaction.options.getString('duration', true);
|
||||||
const { channel } = interaction;
|
const { channel } = interaction;
|
||||||
|
|
||||||
if (channel === null) {
|
if (!isTextBasedChannel(channel)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not fetch channel!',
|
content: 'Could not fetch channel!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -94,7 +97,7 @@ export class SlowmodeCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
if (channel.type !== ChannelType.GuildText) {
|
if (!isTextChannel(channel)) {
|
||||||
info.message = 'Channel is not a text channel!';
|
info.message = 'Channel is not a text channel!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { GuildMember, Message } from 'discord.js';
|
import { GuildMember, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getGuildMember } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class SoftMuteCommand extends Command {
|
export class SoftMuteCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'softmute',
|
name: 'softmute',
|
||||||
@@ -64,39 +66,39 @@ export class SoftMuteCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching the guild!',
|
content: 'Error fetching the guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets guildMember whilst removing the ability of each other variables being null
|
// Gets GuildMember whilst removing the ability of each other variables being null
|
||||||
const guildMember = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if guildMember is null
|
||||||
if (guildMember === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching user!',
|
content: 'Error fetching user!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guildMember.roles.cache.has(IDs.roles.restrictions.softMute)) {
|
if (member.roles.cache.has(IDs.roles.restrictions.softMute)) {
|
||||||
await guildMember.roles.remove(IDs.roles.restrictions.softMute);
|
await member.roles.remove(IDs.roles.restrictions.softMute);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Removed soft muted for ${user}`,
|
content: `Removed soft muted for ${user}`,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await guildMember.roles.add(IDs.roles.restrictions.softMute);
|
await member.roles.add(IDs.roles.restrictions.softMute);
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Soft muted ${user}`,
|
content: `Soft muted ${user}`,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,30 +20,42 @@
|
|||||||
import { RegisterBehavior, Args } from '@sapphire/framework';
|
import { RegisterBehavior, Args } from '@sapphire/framework';
|
||||||
import { Subcommand } from '@sapphire/plugin-subcommands';
|
import { Subcommand } from '@sapphire/plugin-subcommands';
|
||||||
import {
|
import {
|
||||||
ChannelType,
|
|
||||||
EmbedBuilder,
|
EmbedBuilder,
|
||||||
ActionRowBuilder,
|
ActionRowBuilder,
|
||||||
ButtonBuilder,
|
ButtonBuilder,
|
||||||
ButtonInteraction,
|
ButtonInteraction,
|
||||||
ButtonStyle,
|
ButtonStyle,
|
||||||
|
User,
|
||||||
|
Guild,
|
||||||
|
Snowflake,
|
||||||
|
MessageFlagsBitField,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import type { Message, GuildMember, TextChannel } from 'discord.js';
|
import type { Message } from 'discord.js';
|
||||||
import { isMessageInstance } from '@sapphire/discord.js-utilities';
|
|
||||||
import { addExistingUser } from '#utils/database/dbExistingUser';
|
|
||||||
import {
|
import {
|
||||||
addToDatabase,
|
addSusNoteDB,
|
||||||
findNotes,
|
findNotes,
|
||||||
getNote,
|
getNote,
|
||||||
deactivateNote,
|
deactivateNote,
|
||||||
deactivateAllNotes,
|
deactivateAllNotes,
|
||||||
} from '#utils/database/sus';
|
} from '#utils/database/moderation/sus';
|
||||||
import { checkStaff } from '#utils/checker';
|
import { checkStaff } from '#utils/checker';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { createSusLogEmbed } from '#utils/embeds';
|
||||||
|
import { getGuildMember, getTextBasedChannel, getUser } from '#utils/fetcher';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
import {
|
||||||
|
isGuildMember,
|
||||||
|
isTextBasedChannel,
|
||||||
|
isTextChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
// TODO add a check when they join the server to give the user the sus role again
|
// TODO add a check when they join the server to give the user the sus role again
|
||||||
|
|
||||||
export class SusCommand extends Subcommand {
|
export class SusCommand extends Subcommand {
|
||||||
public constructor(context: Subcommand.Context, options: Subcommand.Options) {
|
public constructor(
|
||||||
|
context: Subcommand.LoaderContext,
|
||||||
|
options: Subcommand.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'sus',
|
name: 'sus',
|
||||||
@@ -51,8 +63,8 @@ export class SusCommand extends Subcommand {
|
|||||||
{
|
{
|
||||||
name: 'add',
|
name: 'add',
|
||||||
default: true,
|
default: true,
|
||||||
chatInputRun: 'addNote',
|
chatInputRun: 'addNoteChatInput',
|
||||||
messageRun: 'addMessage',
|
messageRun: 'addNoteMessage',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'view',
|
name: 'view',
|
||||||
@@ -140,7 +152,9 @@ export class SusCommand extends Subcommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Subcommand to add sus note
|
// Subcommand to add sus note
|
||||||
public async addNote(interaction: Subcommand.ChatInputCommandInteraction) {
|
public async addNoteChatInput(
|
||||||
|
interaction: Subcommand.ChatInputCommandInteraction,
|
||||||
|
) {
|
||||||
// Get the arguments
|
// Get the arguments
|
||||||
const user = interaction.options.getUser('user', true);
|
const user = interaction.options.getUser('user', true);
|
||||||
const note = interaction.options.getString('note', true);
|
const note = interaction.options.getString('note', true);
|
||||||
@@ -151,40 +165,122 @@ export class SusCommand extends Subcommand {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const info = await this.addNote(user, mod, note, guild);
|
||||||
|
|
||||||
|
await interaction.reply({
|
||||||
|
content: info.message,
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non Application Command method of adding a sus note
|
||||||
|
public async addNoteMessage(message: Message, args: Args) {
|
||||||
|
// Get arguments
|
||||||
|
let user: User;
|
||||||
|
try {
|
||||||
|
user = await args.pick('user');
|
||||||
|
} catch {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply('User was not provided!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const note = args.finished ? null : await args.rest('string');
|
||||||
|
const mod = message.author;
|
||||||
|
|
||||||
|
if (note === null) {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply('No sus note was provided!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const guild = message.guild;
|
||||||
|
|
||||||
|
if (guild === null) {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply(
|
||||||
|
'Could not find guild! Make sure you run this command in a server.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await this.addNote(user, mod, note, guild);
|
||||||
|
|
||||||
|
if (!info.success) {
|
||||||
|
await message.react('❌');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await message.react('✅');
|
||||||
|
}
|
||||||
|
|
||||||
|
private async addNote(user: User, mod: User, note: string, guild: Guild) {
|
||||||
|
const info = {
|
||||||
|
message: '',
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
|
||||||
// Add the data to the database
|
// Add the data to the database
|
||||||
|
await addSusNoteDB(user.id, mod.id, note);
|
||||||
|
|
||||||
// Check if the user exists on the database
|
// Gives the sus role to the user
|
||||||
const member = guild.members.cache.get(user.id);
|
await this.addSusRole(user, guild);
|
||||||
const modMember = guild.members.cache.get(mod.id);
|
|
||||||
|
|
||||||
if (member === undefined || modMember === undefined) {
|
info.message = `Added the sus note for ${user}: ${note}`;
|
||||||
await interaction.reply({
|
info.success = true;
|
||||||
content: 'Error fetching users!',
|
|
||||||
ephemeral: true,
|
// Log the sus note
|
||||||
});
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.sus);
|
||||||
return;
|
|
||||||
|
if (!isTextBasedChannel(logChannel)) {
|
||||||
|
this.container.logger.error('Sus: Could not fetch log channel.');
|
||||||
|
info.message = `Added a sus note for ${user} but could not find the log channel. This has been logged to the database.`;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
} else if (!logChannel.isSendable()) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'Sus: Does not have permission to message in the log channel.',
|
||||||
|
);
|
||||||
|
info.message = `Added a sus note for ${user} but could not send in the logs channel. This has been logged to the database.`;
|
||||||
|
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user and mod are on the database
|
const message = new EmbedBuilder()
|
||||||
await addExistingUser(member);
|
.setColor('#0099ff')
|
||||||
await addExistingUser(modMember);
|
.setAuthor({
|
||||||
|
name: `Added sus note for ${user.tag}`,
|
||||||
|
iconURL: `${user.displayAvatarURL()}`,
|
||||||
|
})
|
||||||
|
.addFields(
|
||||||
|
{ name: 'User', value: `${user}`, inline: true },
|
||||||
|
{ name: 'Moderator', value: `${mod}`, inline: true },
|
||||||
|
{ name: 'Note', value: note },
|
||||||
|
)
|
||||||
|
.setTimestamp()
|
||||||
|
.setFooter({ text: `ID: ${user.id}` });
|
||||||
|
|
||||||
await addToDatabase(user.id, mod.id, note);
|
await logChannel.send({ embeds: [message] });
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async addSusRole(user: User, guild: Guild) {
|
||||||
|
// Get GuildMember for user to add a sus note for
|
||||||
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
|
if (!isGuildMember(member)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Give the user the sus role they don't already have the sus note
|
// Give the user the sus role they don't already have the sus note
|
||||||
if (!member.roles.cache.has(IDs.roles.restrictions.sus)) {
|
if (!member.roles.cache.has(IDs.roles.restrictions.sus)) {
|
||||||
await member.roles.add(IDs.roles.restrictions.sus);
|
await member.roles.add(IDs.roles.restrictions.sus);
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
content: `${user} note: ${note}`,
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async listNote(interaction: Subcommand.ChatInputCommandInteraction) {
|
public async listNote(interaction: Subcommand.ChatInputCommandInteraction) {
|
||||||
@@ -193,22 +289,15 @@ export class SusCommand extends Subcommand {
|
|||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (guild == null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let staffChannel = false;
|
const staffChannel = checkStaff(interaction.channel);
|
||||||
let { channel } = interaction;
|
|
||||||
if (channel !== null) {
|
|
||||||
if (channel.type === ChannelType.GuildText) {
|
|
||||||
channel = channel as TextChannel;
|
|
||||||
staffChannel = checkStaff(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the sus notes from the database
|
// Gets the sus notes from the database
|
||||||
const notes = await findNotes(user.id, true);
|
const notes = await findNotes(user.id, true);
|
||||||
@@ -217,61 +306,35 @@ export class SusCommand extends Subcommand {
|
|||||||
if (notes.length === 0) {
|
if (notes.length === 0) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `${user} has no sus notes!`,
|
content: `${user} has no sus notes!`,
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the embed to display the sus note
|
// Creates the embed to display the sus note
|
||||||
const noteEmbed = new EmbedBuilder()
|
const noteEmbed = createSusLogEmbed(notes, user, guild);
|
||||||
.setColor('#0099ff')
|
|
||||||
.setTitle(`${notes.length} sus notes for ${user.username}`)
|
|
||||||
.setThumbnail(user.displayAvatarURL());
|
|
||||||
|
|
||||||
// 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
|
|
||||||
) {
|
|
||||||
// Get mod name
|
|
||||||
let mod = notes[i].modId;
|
|
||||||
const modMember = guild.members.cache.get(mod);
|
|
||||||
if (modMember !== undefined) {
|
|
||||||
mod = modMember.displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add sus note to embed
|
|
||||||
noteEmbed.addFields({
|
|
||||||
name: `Sus ID: ${
|
|
||||||
notes[i].id
|
|
||||||
} | Moderator: ${mod} | Date: <t:${Math.floor(
|
|
||||||
notes[i].time.getTime() / 1000,
|
|
||||||
)}>`,
|
|
||||||
value: notes[i].note,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends the notes to the user
|
// Sends the notes to the user
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
embeds: [noteEmbed],
|
embeds: [noteEmbed],
|
||||||
ephemeral: !staffChannel,
|
flags: staffChannel ? undefined : MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async removeNote(interaction: Subcommand.ChatInputCommandInteraction) {
|
public async removeNote(interaction: Subcommand.ChatInputCommandInteraction) {
|
||||||
// Get the arguments
|
// Get the arguments
|
||||||
const noteId = interaction.options.getInteger('id', true);
|
const noteId = interaction.options.getInteger('id', true);
|
||||||
|
const mod = interaction.user;
|
||||||
const { guild, channel } = interaction;
|
const { guild, channel } = interaction;
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (guild === null || channel === null) {
|
if (guild === null || !isTextBasedChannel(channel)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild or channel!',
|
content: 'Error fetching guild or channel!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -283,45 +346,39 @@ export class SusCommand extends Subcommand {
|
|||||||
if (note === null) {
|
if (note === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching note from database!',
|
content: 'Error fetching note from database!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userId = note.userId;
|
||||||
|
const modId = note.modId;
|
||||||
|
|
||||||
// Get user GuildMembers for user and mod and person who ran command
|
// Get user GuildMembers for user and mod and person who ran command
|
||||||
const member = await guild.members.cache.get(note.userId);
|
const user = await getUser(userId);
|
||||||
const mod = await guild.members.cache.get(note.modId);
|
if (!isUser(user)) {
|
||||||
|
|
||||||
// TODO fix if user left the server
|
|
||||||
if (member === undefined || mod === undefined) {
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching users from Discord!',
|
content: 'Error fetching user!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user's name
|
const modCreator = await getUser(modId);
|
||||||
let userName = note.userId;
|
|
||||||
if (member !== undefined) {
|
|
||||||
userName = member.displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mod name
|
const modCreatorDisplay = isUser(modCreator)
|
||||||
let modName = note.modId;
|
? modCreator.displayName
|
||||||
if (mod !== undefined) {
|
: modId;
|
||||||
modName = mod.displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create an embed for the note
|
// Create an embed for the note
|
||||||
const noteEmbed = new EmbedBuilder()
|
const noteEmbed = new EmbedBuilder()
|
||||||
.setColor('#ff0000')
|
.setColor('#ff0000')
|
||||||
.setTitle(`Sus note for ${userName}`)
|
.setTitle(`Sus note for ${user.tag}`)
|
||||||
.setThumbnail(member.displayAvatarURL())
|
.setThumbnail(user.displayAvatarURL())
|
||||||
.addFields({
|
.addFields({
|
||||||
name: `ID: ${noteId} | Moderator: ${modName} | Date: <t:${Math.floor(
|
name: `ID: ${noteId} | Moderator: ${modCreatorDisplay} | Date: <t:${Math.floor(
|
||||||
note.time.getTime() / 1000,
|
note.time.getTime() / 1000,
|
||||||
)}>`,
|
)}>`,
|
||||||
value: note.note,
|
value: note.note,
|
||||||
@@ -343,16 +400,21 @@ export class SusCommand extends Subcommand {
|
|||||||
const message = await interaction.reply({
|
const message = await interaction.reply({
|
||||||
embeds: [noteEmbed],
|
embeds: [noteEmbed],
|
||||||
components: [buttons],
|
components: [buttons],
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Checks if the message is not an APIMessage
|
// Checks if the message is not an APIMessage
|
||||||
if (!isMessageInstance(message)) {
|
if (message.resource === null) {
|
||||||
await interaction.editReply('Failed to retrieve the message :(');
|
await interaction.editReply('Failed to retrieve the message :(');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!channel.isSendable()) {
|
||||||
|
await interaction.editReply('Cannot send messages in this channel!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Listen for the button presses
|
// Listen for the button presses
|
||||||
const collector = channel.createMessageComponentCollector({
|
const collector = channel.createMessageComponentCollector({
|
||||||
max: 1, // Maximum of 1 button press
|
max: 1, // Maximum of 1 button press
|
||||||
@@ -364,18 +426,25 @@ export class SusCommand extends Subcommand {
|
|||||||
if (button.customId === `delete${noteId}`) {
|
if (button.customId === `delete${noteId}`) {
|
||||||
await deactivateNote(noteId);
|
await deactivateNote(noteId);
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `${member}'s sus note (ID: ${noteId}) has been successfully removed`,
|
content: `${user}'s sus note (ID: ${noteId}) has been successfully removed`,
|
||||||
embeds: [],
|
embeds: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO create a new Prisma function to only count and not to get a whole list of sus notes
|
// TODO create a new Prisma function to only count and not to get a whole list of sus notes
|
||||||
// Check how many notes the user has and if 0, then remove sus note
|
// Check how many notes the user has and if 0, then remove sus note
|
||||||
const notes = await findNotes(member.id, true);
|
const notes = await findNotes(userId, true);
|
||||||
|
|
||||||
// Checks if there are no notes on the user and if there's none, remove the sus role
|
// Checks if there are no notes on the user and if there's none, remove the sus role
|
||||||
if (notes.length === 0) {
|
if (notes.length === 0) {
|
||||||
await member.roles.remove(IDs.roles.restrictions.sus);
|
const member = guild.members.cache.get(userId);
|
||||||
|
|
||||||
|
if (isGuildMember(member)) {
|
||||||
|
await member.roles.remove(IDs.roles.restrictions.sus);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logs the removal of the sus note
|
||||||
|
await this.deleteNoteLogger(userId, mod, noteId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -387,31 +456,68 @@ export class SusCommand extends Subcommand {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logs removal of 1 sus note
|
||||||
|
private async deleteNoteLogger(userId: Snowflake, mod: User, noteId: number) {
|
||||||
|
// Find user
|
||||||
|
const user = await getUser(userId);
|
||||||
|
if (!isUser(user)) return;
|
||||||
|
|
||||||
|
// Log the sus note
|
||||||
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.sus);
|
||||||
|
|
||||||
|
if (!isTextBasedChannel(logChannel)) {
|
||||||
|
this.container.logger.error('Sus: Could not fetch log channel.');
|
||||||
|
return;
|
||||||
|
} else if (!logChannel.isSendable()) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'Sus: The bot does not have permission to send in the log channel',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setColor('#28A745')
|
||||||
|
.setAuthor({
|
||||||
|
name: `Removed sus note for ${user.tag}`,
|
||||||
|
iconURL: `${user.displayAvatarURL()}`,
|
||||||
|
})
|
||||||
|
.addFields(
|
||||||
|
{ name: 'User', value: `${user}`, inline: true },
|
||||||
|
{ name: 'Moderator', value: `${mod}`, inline: true },
|
||||||
|
{ name: 'Note ID', value: `${noteId}`, inline: true },
|
||||||
|
)
|
||||||
|
.setTimestamp()
|
||||||
|
.setFooter({ text: `ID: ${user.id}` });
|
||||||
|
|
||||||
|
await logChannel.send({ embeds: [embed] });
|
||||||
|
}
|
||||||
|
|
||||||
public async removeAllNotes(
|
public async removeAllNotes(
|
||||||
interaction: Subcommand.ChatInputCommandInteraction,
|
interaction: Subcommand.ChatInputCommandInteraction,
|
||||||
) {
|
) {
|
||||||
// Get the arguments
|
// Get the arguments
|
||||||
const user = interaction.options.getUser('user', true);
|
const user = interaction.options.getUser('user', true);
|
||||||
|
const mod = interaction.user;
|
||||||
const { guild, channel } = interaction;
|
const { guild, channel } = interaction;
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (guild === null || channel === null) {
|
if (guild === null || !isTextBasedChannel(channel)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild or channel!',
|
content: 'Error fetching guild or channel!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
// Checks if managed to find GuildMember for the user
|
// Checks if managed to find GuildMember for the user
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching user!',
|
content: 'Error fetching user!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -424,8 +530,8 @@ export class SusCommand extends Subcommand {
|
|||||||
if (notes.length === 0) {
|
if (notes.length === 0) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `${user} had no notes!`,
|
content: `${user} had no notes!`,
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -444,10 +550,11 @@ export class SusCommand extends Subcommand {
|
|||||||
) {
|
) {
|
||||||
// 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 = await getGuildMember(mod, guild);
|
||||||
if (modGuildMember !== undefined) {
|
if (isGuildMember(modGuildMember)) {
|
||||||
mod = modGuildMember.displayName;
|
mod = modGuildMember.displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add sus note to embed
|
// Add sus note to embed
|
||||||
noteEmbed.addFields({
|
noteEmbed.addFields({
|
||||||
name: `Sus ID: ${
|
name: `Sus ID: ${
|
||||||
@@ -475,16 +582,21 @@ export class SusCommand extends Subcommand {
|
|||||||
const message = await interaction.reply({
|
const message = await interaction.reply({
|
||||||
embeds: [noteEmbed],
|
embeds: [noteEmbed],
|
||||||
components: [buttons],
|
components: [buttons],
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Checks if the message is not an APIMessage
|
// Checks if the message is not an APIMessage
|
||||||
if (!isMessageInstance(message)) {
|
if (message.resource === null) {
|
||||||
await interaction.editReply('Failed to retrieve the message :(');
|
await interaction.editReply('Failed to retrieve the message :(');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!channel.isSendable()) {
|
||||||
|
await interaction.editReply('Cannot send messages in this channel!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Listen for the button presses
|
// Listen for the button presses
|
||||||
const collector = channel.createMessageComponentCollector({
|
const collector = channel.createMessageComponentCollector({
|
||||||
max: 1, // Maximum of 1 button press
|
max: 1, // Maximum of 1 button press
|
||||||
@@ -501,6 +613,8 @@ export class SusCommand extends Subcommand {
|
|||||||
embeds: [],
|
embeds: [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.deleteAllNotesLogger(user, mod);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove the buttons after they have been clicked
|
// Remove the buttons after they have been clicked
|
||||||
@@ -514,51 +628,34 @@ export class SusCommand extends Subcommand {
|
|||||||
await member.roles.remove(IDs.roles.restrictions.sus);
|
await member.roles.remove(IDs.roles.restrictions.sus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non Application Command method of adding a sus note
|
// Logs removal of 1 sus note
|
||||||
// xlevra begged me to add this... so I guess here it is
|
private async deleteAllNotesLogger(user: User, mod: User) {
|
||||||
public async addMessage(message: Message, args: Args) {
|
// Log the sus note
|
||||||
// Get arguments
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.sus);
|
||||||
let user: GuildMember;
|
|
||||||
try {
|
|
||||||
user = await args.pick('member');
|
|
||||||
} catch {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('User was not provided!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const note = args.finished ? null : await args.rest('string');
|
|
||||||
const mod = message.member;
|
|
||||||
|
|
||||||
if (note === null) {
|
if (!isTextChannel(logChannel)) {
|
||||||
await message.react('❌');
|
this.container.logger.error('Sus: Could not fetch log channel.');
|
||||||
await message.reply('No sus note was provided!');
|
|
||||||
return;
|
return;
|
||||||
}
|
} else if (!logChannel.isSendable()) {
|
||||||
|
this.container.logger.error(
|
||||||
if (mod === null) {
|
'Sus: Could not not send in the log channel.',
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Moderator not found! Try again or contact a developer!',
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user and mod are on the database
|
const embed = new EmbedBuilder()
|
||||||
await addExistingUser(user);
|
.setColor('#28A745')
|
||||||
await addExistingUser(mod);
|
.setAuthor({
|
||||||
|
name: `Purged all sus notes for ${user.tag}`,
|
||||||
|
iconURL: `${user.displayAvatarURL()}`,
|
||||||
|
})
|
||||||
|
.addFields(
|
||||||
|
{ name: 'User', value: `${user}`, inline: true },
|
||||||
|
{ name: 'Moderator', value: `${mod}`, inline: true },
|
||||||
|
)
|
||||||
|
.setTimestamp()
|
||||||
|
.setFooter({ text: `ID: ${user.id}` });
|
||||||
|
|
||||||
await addToDatabase(user.id, mod.id, note);
|
await logChannel.send({ embeds: [embed] });
|
||||||
|
|
||||||
// Give the user the sus role they don't already have the sus note
|
|
||||||
if (!user.roles.cache.has(IDs.roles.restrictions.sus)) {
|
|
||||||
await user.roles.add(IDs.roles.restrictions.sus);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if the user is xlevra to send a very kind message
|
|
||||||
if (mod.id === '259624904746467329') {
|
|
||||||
await message.reply('Fuck you for making me add this feature 🤬');
|
|
||||||
}
|
|
||||||
|
|
||||||
await message.react('✅');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { GuildMember, Message } from 'discord.js';
|
import { GuildMember, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import { addMute, removeMute, checkActive } from '#utils/database/vcMute';
|
import {
|
||||||
|
addMute,
|
||||||
|
removeMute,
|
||||||
|
checkActive,
|
||||||
|
} from '#utils/database/moderation/vcMute';
|
||||||
import { addExistingUser } from '#utils/database/dbExistingUser';
|
import { addExistingUser } from '#utils/database/dbExistingUser';
|
||||||
|
import { getGuildMember } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class VCMuteCommand extends Command {
|
export class VCMuteCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'vcmute',
|
name: 'vcmute',
|
||||||
@@ -62,29 +68,38 @@ export class VCMuteCommand extends Command {
|
|||||||
// Get the arguments
|
// Get the arguments
|
||||||
const user = interaction.options.getUser('user', true);
|
const user = interaction.options.getUser('user', true);
|
||||||
const reason = interaction.options.getString('reason');
|
const reason = interaction.options.getString('reason');
|
||||||
const modUser = interaction.user;
|
const mod = interaction.member;
|
||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
// Checks if all the variables are of the right type
|
// Checks if all the variables are of the right type
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets guildMember whilst removing the ability of each other variables being null
|
// Gets guildMember whilst removing the ability of each other variables being null
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const mod = guild.members.cache.get(modUser.id);
|
|
||||||
|
|
||||||
// Checks if guildMember is null
|
// Checks if `member` was found
|
||||||
if (member === undefined || mod === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching user!',
|
content: 'Error fetching user!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if `mod` was found
|
||||||
|
if (!isGuildMember(mod)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Error fetching your user!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -98,8 +113,8 @@ export class VCMuteCommand extends Command {
|
|||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Removed server mute from ${user}`,
|
content: `Removed server mute from ${user}`,
|
||||||
fetchReply: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
ephemeral: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -114,8 +129,8 @@ export class VCMuteCommand extends Command {
|
|||||||
await addMute(member.id, mod.id, reason);
|
await addMute(member.id, mod.id, reason);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Server muted ${user}`,
|
content: `Server muted ${user}`,
|
||||||
fetchReply: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
ephemeral: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +148,7 @@ export class VCMuteCommand extends Command {
|
|||||||
const reason = args.finished ? null : await args.rest('string');
|
const reason = args.finished ? null : await args.rest('string');
|
||||||
const mod = message.member;
|
const mod = message.member;
|
||||||
|
|
||||||
if (mod === null) {
|
if (!isGuildMember(mod)) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
await message.reply(
|
await message.reply(
|
||||||
'Moderator not found! Try again or contact a developer!',
|
'Moderator not found! Try again or contact a developer!',
|
||||||
|
|||||||
@@ -1,127 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
/*
|
|
||||||
Animal Rights Advocates Discord Bot
|
|
||||||
Copyright (C) 2023 Anthony Berg
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Args, Command } from '@sapphire/framework';
|
|
||||||
import type { User, Message, Snowflake, Guild } from 'discord.js';
|
|
||||||
import { addExistingUser, updateUser } from '#utils/database/dbExistingUser';
|
|
||||||
import { addWarn } from '#utils/database/warnings';
|
|
||||||
|
|
||||||
/*
|
|
||||||
This command is not intended to be functional for now, this is purely to log
|
|
||||||
warnings onto a database, so if we were to switch purely to ARA Bot, it would
|
|
||||||
mean we would have a lot of the warns already in the database.
|
|
||||||
*/
|
|
||||||
export class WarnCommand extends Command {
|
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
|
||||||
super(context, {
|
|
||||||
...options,
|
|
||||||
name: 'warn',
|
|
||||||
description: 'Warns a user (only used for logging to a database for now)',
|
|
||||||
preconditions: [['CoordinatorOnly', 'ModOnly']],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async messageRun(message: Message, args: Args) {
|
|
||||||
// Get arguments
|
|
||||||
let user: User;
|
|
||||||
try {
|
|
||||||
user = await args.pick('user');
|
|
||||||
} catch {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('User was not provided!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const reason = args.finished ? null : await args.rest('string');
|
|
||||||
const mod = message.member;
|
|
||||||
|
|
||||||
if (reason === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Warn reason was not provided!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Moderator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
|
||||||
|
|
||||||
if (guild === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Guild not found! Try again or contact a developer!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const warn = await this.warn(user.id, mod.id, reason, guild);
|
|
||||||
|
|
||||||
if (!warn.success) {
|
|
||||||
await message.react('❌');
|
|
||||||
}
|
|
||||||
|
|
||||||
// await message.react('✅');
|
|
||||||
}
|
|
||||||
|
|
||||||
private async warn(
|
|
||||||
userId: Snowflake,
|
|
||||||
modId: Snowflake,
|
|
||||||
reason: string,
|
|
||||||
guild: Guild,
|
|
||||||
) {
|
|
||||||
const info = {
|
|
||||||
message: '',
|
|
||||||
success: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gets mod's GuildMember
|
|
||||||
const mod = guild.members.cache.get(modId);
|
|
||||||
|
|
||||||
// Checks if guildMember is null
|
|
||||||
if (mod === undefined) {
|
|
||||||
info.message = 'Error fetching mod!';
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if mod is in database
|
|
||||||
await updateUser(mod);
|
|
||||||
|
|
||||||
// Gets guildMember
|
|
||||||
let member = guild.members.cache.get(userId);
|
|
||||||
|
|
||||||
if (member === undefined) {
|
|
||||||
member = await guild.members.fetch(userId).catch(() => undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (member === undefined) {
|
|
||||||
info.message = 'User is not on this server';
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
await addExistingUser(member);
|
|
||||||
|
|
||||||
await addWarn(userId, modId, reason);
|
|
||||||
|
|
||||||
info.message = `Warned ${member}`;
|
|
||||||
info.success = true;
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
180
src/commands/mod/warning/deleteWarning.ts
Normal file
180
src/commands/mod/warning/deleteWarning.ts
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
/*
|
||||||
|
Animal Rights Advocates Discord Bot
|
||||||
|
Copyright (C) 2024 Anthony Berg
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
|
import type { Message, User } from 'discord.js';
|
||||||
|
import IDs from '#utils/ids';
|
||||||
|
import {
|
||||||
|
deleteWarning,
|
||||||
|
fetchWarning,
|
||||||
|
} from '#utils/database/moderation/warnings';
|
||||||
|
import { checkStaff } from '#utils/checker';
|
||||||
|
import { getTextBasedChannel, getUser } from '#utils/fetcher';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
import { isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
|
export class DeleteWarningCommand extends Command {
|
||||||
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
|
super(context, {
|
||||||
|
...options,
|
||||||
|
name: 'deletewarning',
|
||||||
|
aliases: ['delwarn', 'removewarning'],
|
||||||
|
description: 'Deletes a warning',
|
||||||
|
preconditions: ['ModOnly'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers that this is a slash command
|
||||||
|
public override registerApplicationCommands(registry: Command.Registry) {
|
||||||
|
registry.registerChatInputCommand(
|
||||||
|
(builder) =>
|
||||||
|
builder
|
||||||
|
.setName(this.name)
|
||||||
|
.setDescription(this.description)
|
||||||
|
.addIntegerOption((option) =>
|
||||||
|
option
|
||||||
|
.setName('id')
|
||||||
|
.setDescription('ID for the warning')
|
||||||
|
.setRequired(true),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command run
|
||||||
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
|
// Get the arguments
|
||||||
|
const warningId = interaction.options.getInteger('id', true);
|
||||||
|
const mod = interaction.user;
|
||||||
|
|
||||||
|
const staffChannel = checkStaff(interaction.channel);
|
||||||
|
|
||||||
|
await interaction.deferReply({
|
||||||
|
flags: staffChannel ? undefined : MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
|
const info = await this.deleteWarning(warningId, mod);
|
||||||
|
|
||||||
|
await interaction.editReply({
|
||||||
|
content: info.message,
|
||||||
|
embeds: info.embeds,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non Application Command method for removing a warning
|
||||||
|
public async messageRun(message: Message, args: Args) {
|
||||||
|
// Get arguments
|
||||||
|
let warningId: number;
|
||||||
|
try {
|
||||||
|
warningId = await args.pick('integer');
|
||||||
|
} catch {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.react('Correct warning ID not provided!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mod = message.author;
|
||||||
|
|
||||||
|
const { guild } = message;
|
||||||
|
|
||||||
|
if (guild === null) {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply('Guild not found! Try again or contact a developer!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await this.deleteWarning(warningId, mod);
|
||||||
|
|
||||||
|
await message.reply({ content: info.message, embeds: info.embeds });
|
||||||
|
if (!info.success) {
|
||||||
|
await message.react('❌');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async deleteWarning(warningId: number, mod: User) {
|
||||||
|
const info = {
|
||||||
|
message: '',
|
||||||
|
embeds: [] as EmbedBuilder[],
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const warning = await fetchWarning(warningId);
|
||||||
|
|
||||||
|
if (warning === null) {
|
||||||
|
info.message = `Warning ID \`${warningId}\` not found!`;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
await deleteWarning(warningId);
|
||||||
|
info.success = true;
|
||||||
|
|
||||||
|
const userId = warning.userId;
|
||||||
|
const user = await getUser(userId);
|
||||||
|
|
||||||
|
if (!isUser(user)) {
|
||||||
|
info.message = `Deleted warning ID \`${warningId}\`, but the user could not be found!`;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log the warnings deletion
|
||||||
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.sus);
|
||||||
|
|
||||||
|
if (!isTextChannel(logChannel)) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'Delete Warning: Could not fetch log channel',
|
||||||
|
);
|
||||||
|
info.message =
|
||||||
|
`Deleted warning for ${user} (Warning ID: ${warningId} but ` +
|
||||||
|
'could not find the log channel.';
|
||||||
|
|
||||||
|
return info;
|
||||||
|
} else if (!logChannel.isSendable()) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'Delete Warning: The bot does not have permission to send in the logs channel!',
|
||||||
|
);
|
||||||
|
info.message =
|
||||||
|
`Deleted warning for ${user} (Warning ID: ${warningId} but ` +
|
||||||
|
"But this hasn't been logged in a text channel as the bot does not have permission to send logs!";
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = new EmbedBuilder()
|
||||||
|
.setColor('#28A745')
|
||||||
|
.setAuthor({
|
||||||
|
name: `Removed warning for ${user.tag}`,
|
||||||
|
iconURL: `${user.displayAvatarURL()}`,
|
||||||
|
})
|
||||||
|
.addFields(
|
||||||
|
{ name: 'User', value: `${user}`, inline: true },
|
||||||
|
{ name: 'Moderator', value: `${mod}`, inline: true },
|
||||||
|
{ name: 'Warning ID', value: `${warningId}`, inline: true },
|
||||||
|
)
|
||||||
|
.setTimestamp()
|
||||||
|
.setFooter({ text: `ID: ${userId}` });
|
||||||
|
|
||||||
|
await logChannel.send({ embeds: [message] });
|
||||||
|
|
||||||
|
info.message = `Deleted warning for ${user}`;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
220
src/commands/mod/warning/warn.ts
Normal file
220
src/commands/mod/warning/warn.ts
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
/*
|
||||||
|
Animal Rights Advocates Discord Bot
|
||||||
|
Copyright (C) 2023, 2024 Anthony Berg
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
|
import {
|
||||||
|
EmbedBuilder,
|
||||||
|
Guild,
|
||||||
|
Message,
|
||||||
|
MessageFlagsBitField,
|
||||||
|
Snowflake,
|
||||||
|
User,
|
||||||
|
} from 'discord.js';
|
||||||
|
import { updateUser } from '#utils/database/dbExistingUser';
|
||||||
|
import { addWarn } from '#utils/database/moderation/warnings';
|
||||||
|
import IDs from '#utils/ids';
|
||||||
|
import { getGuildMember, getTextBasedChannel, getUser } from '#utils/fetcher';
|
||||||
|
import { isGuildMember, isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
|
||||||
|
export class WarnCommand extends Command {
|
||||||
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
|
super(context, {
|
||||||
|
...options,
|
||||||
|
name: 'warn',
|
||||||
|
description: 'Warns a user',
|
||||||
|
preconditions: [['CoordinatorOnly', 'ModOnly']],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers that this is a slash command
|
||||||
|
public override registerApplicationCommands(registry: Command.Registry) {
|
||||||
|
registry.registerChatInputCommand(
|
||||||
|
(builder) =>
|
||||||
|
builder
|
||||||
|
.setName(this.name)
|
||||||
|
.setDescription(this.description)
|
||||||
|
.addUserOption((option) =>
|
||||||
|
option
|
||||||
|
.setName('user')
|
||||||
|
.setDescription('User to warn')
|
||||||
|
.setRequired(true),
|
||||||
|
)
|
||||||
|
.addStringOption((option) =>
|
||||||
|
option
|
||||||
|
.setName('reason')
|
||||||
|
.setDescription('Reason for the warning')
|
||||||
|
.setRequired(true),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command run
|
||||||
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
|
// Get the arguments
|
||||||
|
const user = interaction.options.getUser('user', true);
|
||||||
|
const reason = interaction.options.getString('reason', true);
|
||||||
|
const mod = interaction.user;
|
||||||
|
const { guild } = interaction;
|
||||||
|
|
||||||
|
// Checks if all the variables are of the right type
|
||||||
|
if (guild === null) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Error fetching guild!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
withResponse: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
|
const info = await this.warn(user.id, mod.id, reason, guild);
|
||||||
|
|
||||||
|
await interaction.editReply({
|
||||||
|
content: info.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non Application Command method for warning a user
|
||||||
|
public async messageRun(message: Message, args: Args) {
|
||||||
|
// Get arguments
|
||||||
|
let user: User;
|
||||||
|
try {
|
||||||
|
user = await args.pick('user');
|
||||||
|
} catch {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply('User was not provided!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const reason = args.finished ? null : await args.rest('string');
|
||||||
|
const mod = message.author;
|
||||||
|
|
||||||
|
if (reason === null) {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply('Warn reason was not provided!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { guild } = message;
|
||||||
|
|
||||||
|
if (guild === null) {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply('Guild not found! Try again or contact a developer!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const warn = await this.warn(user.id, mod.id, reason, guild);
|
||||||
|
|
||||||
|
if (!warn.success) {
|
||||||
|
await message.react('❌');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await message.react('✅');
|
||||||
|
}
|
||||||
|
|
||||||
|
private async warn(
|
||||||
|
userId: Snowflake,
|
||||||
|
modId: Snowflake,
|
||||||
|
reason: string,
|
||||||
|
guild: Guild,
|
||||||
|
) {
|
||||||
|
const info = {
|
||||||
|
message: '',
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gets mod's GuildMember
|
||||||
|
const mod = await getGuildMember(modId, guild);
|
||||||
|
|
||||||
|
// Checks if guildMember is null
|
||||||
|
if (!isGuildMember(mod)) {
|
||||||
|
info.message = 'Error fetching mod!';
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if mod is in database
|
||||||
|
await updateUser(mod);
|
||||||
|
|
||||||
|
// Gets User for person being restricted
|
||||||
|
const user = await getUser(userId);
|
||||||
|
|
||||||
|
if (!isUser(user)) {
|
||||||
|
info.message = 'Error fetching user';
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
await addWarn(userId, modId, reason);
|
||||||
|
|
||||||
|
info.message = `Warned ${user}`;
|
||||||
|
info.success = true;
|
||||||
|
|
||||||
|
// DM the reason
|
||||||
|
|
||||||
|
const dmEmbed = new EmbedBuilder()
|
||||||
|
.setColor('#FF6700')
|
||||||
|
.setAuthor({
|
||||||
|
name: "You've been warned!",
|
||||||
|
iconURL: `${user.displayAvatarURL()}`,
|
||||||
|
})
|
||||||
|
.addFields({ name: 'Reason', value: reason })
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await user.send({ embeds: [dmEmbed] }).catch(() => {});
|
||||||
|
|
||||||
|
// Log the ban
|
||||||
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.sus);
|
||||||
|
|
||||||
|
if (!isTextChannel(logChannel)) {
|
||||||
|
this.container.logger.error('Warn: Could not fetch log channel');
|
||||||
|
info.message = `Warned ${user} but could not find the log channel. This has been logged to the database.`;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
} else if (!logChannel.isSendable()) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'Warn: The bot does not have permission to send in the logs channel!',
|
||||||
|
);
|
||||||
|
info.message = `Warned ${user}, but the bot does not have permission to send in the logs channel!`;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = new EmbedBuilder()
|
||||||
|
.setColor('#FF6700')
|
||||||
|
.setAuthor({
|
||||||
|
name: `Warned ${user.tag}`,
|
||||||
|
iconURL: `${user.displayAvatarURL()}`,
|
||||||
|
})
|
||||||
|
.addFields(
|
||||||
|
{ name: 'User', value: `${user}`, inline: true },
|
||||||
|
{ name: 'Moderator', value: `${mod}`, inline: true },
|
||||||
|
{ name: 'Reason', value: reason },
|
||||||
|
)
|
||||||
|
.setTimestamp()
|
||||||
|
.setFooter({ text: `ID: ${userId}` });
|
||||||
|
|
||||||
|
await logChannel.send({ embeds: [message] });
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
164
src/commands/mod/warning/warnings.ts
Normal file
164
src/commands/mod/warning/warnings.ts
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
/*
|
||||||
|
Animal Rights Advocates Discord Bot
|
||||||
|
Copyright (C) 2024 Anthony Berg
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
|
import { EmbedBuilder, MessageFlagsBitField } from 'discord.js';
|
||||||
|
import type { Message, Guild, User } from 'discord.js';
|
||||||
|
import IDs from '#utils/ids';
|
||||||
|
import { fetchWarnings } from '#utils/database/moderation/warnings';
|
||||||
|
import { checkStaff } from '#utils/checker';
|
||||||
|
import { createWarningsEmbed } from '#utils/embeds';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
import { isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
import { getUser } from '#utils/fetcher';
|
||||||
|
|
||||||
|
export class WarningsCommand extends Command {
|
||||||
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
|
super(context, {
|
||||||
|
...options,
|
||||||
|
name: 'warnings',
|
||||||
|
aliases: ['warninglog', 'warnlog'],
|
||||||
|
description: 'Shows all the warnings for the user',
|
||||||
|
preconditions: ['ModOnly'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers that this is a slash command
|
||||||
|
public override registerApplicationCommands(registry: Command.Registry) {
|
||||||
|
registry.registerChatInputCommand(
|
||||||
|
(builder) =>
|
||||||
|
builder
|
||||||
|
.setName(this.name)
|
||||||
|
.setDescription(this.description)
|
||||||
|
.addUserOption((option) =>
|
||||||
|
option
|
||||||
|
.setName('user')
|
||||||
|
.setDescription('User to check the warnings for')
|
||||||
|
.setRequired(true),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command run
|
||||||
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
|
// Get the arguments
|
||||||
|
const user = interaction.options.getUser('user', true);
|
||||||
|
const { guild } = interaction;
|
||||||
|
|
||||||
|
// Checks if all the variables are of the right type
|
||||||
|
if (guild === null) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Error fetching guild!',
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
withResponse: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const staffChannel = checkStaff(interaction.channel);
|
||||||
|
|
||||||
|
await interaction.deferReply({
|
||||||
|
flags: staffChannel ? undefined : MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
|
const info = await this.warnings(user, guild);
|
||||||
|
|
||||||
|
await interaction.editReply({
|
||||||
|
content: info.message,
|
||||||
|
embeds: info.embeds,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non Application Command method for fetching warnings
|
||||||
|
public async messageRun(message: Message, args: Args) {
|
||||||
|
// Get arguments
|
||||||
|
let user: User | undefined;
|
||||||
|
try {
|
||||||
|
user = await args.pick('user');
|
||||||
|
} catch {
|
||||||
|
user = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { guild } = message;
|
||||||
|
|
||||||
|
if (guild === null) {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply('Guild not found! Try again or contact a developer!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isUser(user)) {
|
||||||
|
const { channel } = message;
|
||||||
|
|
||||||
|
if (!isTextChannel(channel)) {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply('User was not provided!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let topic: string[];
|
||||||
|
|
||||||
|
if (channel.parentId === IDs.categories.modMail) {
|
||||||
|
// Checks if the channel topic has the user's snowflake
|
||||||
|
if (channel.topic !== null) {
|
||||||
|
topic = channel.topic.split(' ');
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
|
const userId = topic[2];
|
||||||
|
|
||||||
|
user = await getUser(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isUser(user)) {
|
||||||
|
await message.react('❌');
|
||||||
|
await message.reply(
|
||||||
|
'User was not provided! (You most likely provided a user incorrectly.)',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await this.warnings(user, guild);
|
||||||
|
|
||||||
|
await message.reply({ content: info.message, embeds: info.embeds });
|
||||||
|
}
|
||||||
|
|
||||||
|
private async warnings(user: User, guild: Guild) {
|
||||||
|
const info = {
|
||||||
|
message: '',
|
||||||
|
embeds: [] as EmbedBuilder[],
|
||||||
|
};
|
||||||
|
|
||||||
|
const warnings = await fetchWarnings(user.id);
|
||||||
|
|
||||||
|
if (warnings.length === 0) {
|
||||||
|
info.message = `${user} user has no warnings.`;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an embed to display the warnings
|
||||||
|
const embed = createWarningsEmbed(warnings, user, guild);
|
||||||
|
|
||||||
|
info.embeds.push(embed);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,12 @@
|
|||||||
|
|
||||||
import { Subcommand } from '@sapphire/plugin-subcommands';
|
import { Subcommand } from '@sapphire/plugin-subcommands';
|
||||||
import { RegisterBehavior } from '@sapphire/framework';
|
import { RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Snowflake } from 'discord.js';
|
import {
|
||||||
|
ChannelType,
|
||||||
|
MessageFlagsBitField,
|
||||||
|
PermissionsBitField,
|
||||||
|
Snowflake,
|
||||||
|
} from 'discord.js';
|
||||||
import { updateUser } from '#utils/database/dbExistingUser';
|
import { updateUser } from '#utils/database/dbExistingUser';
|
||||||
import {
|
import {
|
||||||
addStatUser,
|
addStatUser,
|
||||||
@@ -36,9 +41,17 @@ import {
|
|||||||
} from '#utils/database/outreach';
|
} from '#utils/database/outreach';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
|
import {
|
||||||
|
isGuildMember,
|
||||||
|
isTextBasedChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
import { getGuildMember, getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
|
||||||
export class OutreachCommand extends Subcommand {
|
export class OutreachCommand extends Subcommand {
|
||||||
public constructor(context: Subcommand.Context, options: Subcommand.Options) {
|
public constructor(
|
||||||
|
context: Subcommand.LoaderContext,
|
||||||
|
options: Subcommand.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'outreach',
|
name: 'outreach',
|
||||||
@@ -63,7 +76,6 @@ export class OutreachCommand extends Subcommand {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
preconditions: ['ModOnly'],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,31 +194,29 @@ export class OutreachCommand extends Subcommand {
|
|||||||
interaction: Subcommand.ChatInputCommandInteraction,
|
interaction: Subcommand.ChatInputCommandInteraction,
|
||||||
) {
|
) {
|
||||||
// const start = interaction.options.getBoolean('start');
|
// const start = interaction.options.getBoolean('start');
|
||||||
const modUser = interaction.user;
|
const mod = interaction.member;
|
||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Mod or guild was not found!',
|
content: 'Mod or guild was not found!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = guild.members.cache.get(modUser.id);
|
if (!isGuildMember(mod)) {
|
||||||
|
|
||||||
if (mod === undefined) {
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Mod was not found!',
|
content: 'Outreach Leader was not found!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mod.roles.cache.has(IDs.roles.staff.outreachCoordinator)) {
|
if (!mod.roles.cache.has(IDs.roles.staff.outreachLeader)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'You need to be an Outreach Coordinator to run this command!',
|
content: 'You need to be an Outreach Leader to run this command!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -214,52 +224,52 @@ export class OutreachCommand extends Subcommand {
|
|||||||
if (await checkActiveEvent()) {
|
if (await checkActiveEvent()) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'There is already an active event!',
|
content: 'There is already an active event!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await updateUser(mod);
|
await updateUser(mod);
|
||||||
|
|
||||||
await createEvent(modUser.id);
|
await createEvent(mod.id);
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Created the event!',
|
content: 'Created the event!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async eventEnd(interaction: Subcommand.ChatInputCommandInteraction) {
|
public async eventEnd(interaction: Subcommand.ChatInputCommandInteraction) {
|
||||||
const modUser = interaction.user;
|
const mod = interaction.member;
|
||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Guild not found!',
|
content: 'Guild not found!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = guild.members.cache.get(modUser.id);
|
if (!isGuildMember(mod)) {
|
||||||
|
|
||||||
if (mod === undefined) {
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Your guild member was not found!',
|
content: 'Your guild member was not found!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mod.roles.cache.has(IDs.roles.staff.outreachCoordinator)) {
|
if (!mod.roles.cache.has(IDs.roles.staff.outreachLeader)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'You need to be an Outreach Coordinator to run this command!',
|
content: 'You need to be an Outreach Leader to run this command!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const event = await getCurrentEvent();
|
const event = await getCurrentEvent();
|
||||||
|
|
||||||
@@ -272,7 +282,8 @@ export class OutreachCommand extends Subcommand {
|
|||||||
|
|
||||||
stat.forEach(({ role }) => {
|
stat.forEach(({ role }) => {
|
||||||
if (role !== null) {
|
if (role !== null) {
|
||||||
guild.roles.delete(role.roleId);
|
guild.roles.delete(role.roleId); // Delete role
|
||||||
|
guild.channels.delete(role.channelId); // Delete VC
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -296,9 +307,9 @@ export class OutreachCommand extends Subcommand {
|
|||||||
educated += group.educated;
|
educated += group.educated;
|
||||||
});
|
});
|
||||||
|
|
||||||
const activist = guild.channels.cache.get(IDs.channels.activism.activism);
|
const activist = await getTextBasedChannel(IDs.channels.activism.activism);
|
||||||
|
|
||||||
if (activist === undefined || !activist.isTextBased()) {
|
if (!isTextBasedChannel(activist)) {
|
||||||
await interaction.editReply(
|
await interaction.editReply(
|
||||||
'Event has now ended, but could not post statistics!',
|
'Event has now ended, but could not post statistics!',
|
||||||
);
|
);
|
||||||
@@ -348,12 +359,14 @@ export class OutreachCommand extends Subcommand {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Guild not found!',
|
content: 'Guild not found!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
if ((await getStatFromLeader(leader.id)) !== null) {
|
if ((await getStatFromLeader(leader.id)) !== null) {
|
||||||
await interaction.editReply(
|
await interaction.editReply(
|
||||||
@@ -374,9 +387,9 @@ export class OutreachCommand extends Subcommand {
|
|||||||
const statGroups = await getStatGroups(event.id);
|
const statGroups = await getStatGroups(event.id);
|
||||||
const groupNo = statGroups.length + 1;
|
const groupNo = statGroups.length + 1;
|
||||||
|
|
||||||
const leaderMember = await guild.members.cache.get(leader.id);
|
const leaderMember = await getGuildMember(leader.id, guild);
|
||||||
|
|
||||||
if (leaderMember === undefined) {
|
if (!isGuildMember(leaderMember)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `Could not find ${leader}'s guild member.`,
|
content: `Could not find ${leader}'s guild member.`,
|
||||||
});
|
});
|
||||||
@@ -385,14 +398,66 @@ export class OutreachCommand extends Subcommand {
|
|||||||
|
|
||||||
await updateUser(leaderMember);
|
await updateUser(leaderMember);
|
||||||
|
|
||||||
|
// Create role for group
|
||||||
const role = await guild.roles.create({
|
const role = await guild.roles.create({
|
||||||
name: `Outreach Group ${groupNo}`,
|
name: `Outreach Group ${groupNo}`,
|
||||||
|
mentionable: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await createStat(event.id, leader.id, role.id);
|
// Create a voice channel for group
|
||||||
|
const channel = await guild.channels.create({
|
||||||
|
name: `Outreach Group ${groupNo}`,
|
||||||
|
type: ChannelType.GuildVoice,
|
||||||
|
parent: IDs.categories.activism,
|
||||||
|
permissionOverwrites: [
|
||||||
|
{
|
||||||
|
id: guild.roles.everyone,
|
||||||
|
deny: [
|
||||||
|
PermissionsBitField.Flags.SendMessages,
|
||||||
|
PermissionsBitField.Flags.Connect,
|
||||||
|
PermissionsBitField.Flags.ViewChannel,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: IDs.roles.vegan.activist,
|
||||||
|
allow: [PermissionsBitField.Flags.ViewChannel],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: role.id, // Permissions for the specific group
|
||||||
|
allow: [
|
||||||
|
PermissionsBitField.Flags.SendMessages,
|
||||||
|
PermissionsBitField.Flags.Connect,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: IDs.roles.staff.outreachLeader,
|
||||||
|
allow: [
|
||||||
|
PermissionsBitField.Flags.SendMessages,
|
||||||
|
PermissionsBitField.Flags.Connect,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create stats in database
|
||||||
|
await createStat(event.id, leader.id, role.id, channel.id);
|
||||||
|
|
||||||
|
// Give group leader role
|
||||||
await leaderMember.roles.add(role);
|
await leaderMember.roles.add(role);
|
||||||
|
|
||||||
|
// Send message in VC with a welcome and reminder
|
||||||
|
await channel.send(
|
||||||
|
`Welcome ${role}, ${leaderMember} is going to be the leader of your group!\n\n` +
|
||||||
|
'Remember to keep track of stats during activism with `/outreach group update` and' +
|
||||||
|
'to have these questions in mind whilst doing activism:\n' +
|
||||||
|
'- How many said would go vegan?\n' +
|
||||||
|
'- How many seriously considered being vegan?\n' +
|
||||||
|
'- How many people had anti-vegan viewpoints?\n' +
|
||||||
|
'- How many thanked you for the conversation?\n' +
|
||||||
|
'- How many said they would watch a vegan documentary?\n' +
|
||||||
|
'- How many got educated on veganism or the animal industry?',
|
||||||
|
);
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `Created a group with the leader being ${leader}`,
|
content: `Created a group with the leader being ${leader}`,
|
||||||
});
|
});
|
||||||
@@ -401,18 +466,27 @@ export class OutreachCommand extends Subcommand {
|
|||||||
public async groupAdd(interaction: Subcommand.ChatInputCommandInteraction) {
|
public async groupAdd(interaction: Subcommand.ChatInputCommandInteraction) {
|
||||||
const user = interaction.options.getUser('user', true);
|
const user = interaction.options.getUser('user', true);
|
||||||
const group = interaction.options.getRole('group');
|
const group = interaction.options.getRole('group');
|
||||||
const leader = interaction.user;
|
const leader = interaction.member;
|
||||||
const { guild } = interaction;
|
const { guild } = interaction;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not find guild!',
|
content: 'Could not find guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
if (!isGuildMember(leader)) {
|
||||||
|
await interaction.editReply({
|
||||||
|
content: 'Could not find your GuildMember!',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
let statId: number;
|
let statId: number;
|
||||||
let roleId: Snowflake | undefined;
|
let roleId: Snowflake | undefined;
|
||||||
@@ -428,18 +502,9 @@ export class OutreachCommand extends Subcommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const leaderMember = guild.members.cache.get(leader.id);
|
|
||||||
|
|
||||||
if (leaderMember === undefined) {
|
|
||||||
await interaction.editReply({
|
|
||||||
content: 'Could not find your GuildMember in cache!',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
leader.id !== stat.stat.leaderId &&
|
leader.id !== stat.stat.leaderId &&
|
||||||
!leaderMember.roles.cache.has(IDs.roles.staff.outreachCoordinator)
|
!leader.roles.cache.has(IDs.roles.staff.outreachLeader)
|
||||||
) {
|
) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `You are not the leader for ${group}`,
|
content: `You are not the leader for ${group}`,
|
||||||
@@ -471,9 +536,9 @@ export class OutreachCommand extends Subcommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: 'Could not fetch the member!',
|
content: 'Could not fetch the member!',
|
||||||
});
|
});
|
||||||
@@ -513,15 +578,9 @@ export class OutreachCommand extends Subcommand {
|
|||||||
educated: educated !== null ? educated : 0,
|
educated: educated !== null ? educated : 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (leader === null) {
|
await interaction.deferReply({
|
||||||
await interaction.reply({
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
content: 'Could not find your user!',
|
});
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
|
||||||
|
|
||||||
const stat = await getStatFromLeader(leader.id);
|
const stat = await getStatFromLeader(leader.id);
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class BookClubCommand extends Command {
|
export class BookClubCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'bookclub',
|
name: 'bookclub',
|
||||||
@@ -62,13 +65,15 @@ export class BookClubCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageBookClub(user, mod, guild);
|
const info = await this.manageBookClub(user, mod, guild);
|
||||||
|
|
||||||
@@ -88,14 +93,6 @@ export class BookClubCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Event coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,16 +112,16 @@ export class BookClubCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const bookClub = guild.roles.cache.get(IDs.roles.bookClub);
|
const bookClub = await getRole(IDs.roles.bookClub, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bookClub === undefined) {
|
if (!isRole(bookClub)) {
|
||||||
info.message = 'Error fetching book club role from cache!';
|
info.message = 'Error fetching book club role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class DebateHostCommand extends Command {
|
export class DebateHostCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'debatehost',
|
name: 'debatehost',
|
||||||
@@ -63,13 +66,15 @@ export class DebateHostCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageDebateHost(user, mod, guild);
|
const info = await this.manageDebateHost(user, mod, guild);
|
||||||
|
|
||||||
@@ -89,14 +94,6 @@ export class DebateHostCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Event coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -116,16 +113,16 @@ export class DebateHostCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const debateHost = guild.roles.cache.get(IDs.roles.debateHost);
|
const debateHost = await getRole(IDs.roles.debateHost, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debateHost === undefined) {
|
if (!isRole(debateHost)) {
|
||||||
info.message = 'Error fetching debate host role from cache!';
|
info.message = 'Error fetching debate host role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class GameNightHostCommand extends Command {
|
export class GameNightHostCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'gamenight',
|
name: 'gamenight',
|
||||||
@@ -62,13 +65,15 @@ export class GameNightHostCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageGameNight(user, mod, guild);
|
const info = await this.manageGameNight(user, mod, guild);
|
||||||
|
|
||||||
@@ -88,14 +93,6 @@ export class GameNightHostCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Event coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,16 +112,16 @@ export class GameNightHostCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const gameNightHost = guild.roles.cache.get(IDs.roles.gameNightHost);
|
const gameNightHost = await getRole(IDs.roles.gameNightHost, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameNightHost === undefined) {
|
if (!isRole(gameNightHost)) {
|
||||||
info.message = 'Error fetching game night host role from cache!';
|
info.message = 'Error fetching game night host role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class GuestCommand extends Command {
|
export class GuestCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'guest',
|
name: 'guest',
|
||||||
@@ -62,13 +65,15 @@ export class GuestCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageGuest(user, mod, guild);
|
const info = await this.manageGuest(user, mod, guild);
|
||||||
|
|
||||||
@@ -88,14 +93,6 @@ export class GuestCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Event coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,16 +112,16 @@ export class GuestCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const guest = guild.roles.cache.get(IDs.roles.guest);
|
const guest = await getRole(IDs.roles.guest, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guest === undefined) {
|
if (!isRole(guest)) {
|
||||||
info.message = 'Error fetching guest role from cache!';
|
info.message = 'Error fetching guest role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class MentorCommand extends Command {
|
export class MentorCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'mentor',
|
name: 'mentor',
|
||||||
@@ -63,13 +66,15 @@ export class MentorCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageMentor(user, mod, guild);
|
const info = await this.manageMentor(user, mod, guild);
|
||||||
|
|
||||||
@@ -89,14 +94,6 @@ export class MentorCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Mentor coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -116,16 +113,16 @@ export class MentorCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const mentor = guild.roles.cache.get(IDs.roles.staff.mentor);
|
const mentor = await getRole(IDs.roles.staff.mentor, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mentor === undefined) {
|
if (!isRole(mentor)) {
|
||||||
info.message = 'Error fetching mentor role from cache!';
|
info.message = 'Error fetching mentor role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class ModCommand extends Command {
|
export class ModCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'mod',
|
name: 'mod',
|
||||||
@@ -62,13 +65,15 @@ export class ModCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageMod(user, mod, guild);
|
const info = await this.manageMod(user, mod, guild);
|
||||||
|
|
||||||
@@ -88,14 +93,6 @@ export class ModCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Mod coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,16 +112,16 @@ export class ModCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const moderator = guild.roles.cache.get(IDs.roles.staff.moderator);
|
const moderator = await getRole(IDs.roles.staff.moderator, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moderator === undefined) {
|
if (!isRole(moderator)) {
|
||||||
info.message = 'Error fetching the moderator role from cache!';
|
info.message = 'Error fetching the moderator role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class RestrictedAccessCommand extends Command {
|
export class RestrictedAccessCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'restrictedaccess',
|
name: 'restrictedaccess',
|
||||||
@@ -63,13 +66,15 @@ export class RestrictedAccessCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageRestrictedAccess(user, mod, guild);
|
const info = await this.manageRestrictedAccess(user, mod, guild);
|
||||||
|
|
||||||
@@ -89,14 +94,6 @@ export class RestrictedAccessCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Mod coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -116,16 +113,16 @@ export class RestrictedAccessCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const restricted = guild.roles.cache.get(IDs.roles.staff.restricted);
|
const restricted = await getRole(IDs.roles.staff.restricted, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restricted === undefined) {
|
if (!isRole(restricted)) {
|
||||||
info.message = 'Error fetching the restricted access role from cache!';
|
info.message = 'Error fetching the restricted access role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class StageHostCommand extends Command {
|
export class StageHostCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'stagehost',
|
name: 'stagehost',
|
||||||
@@ -62,13 +65,15 @@ export class StageHostCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageStageHost(user, mod, guild);
|
const info = await this.manageStageHost(user, mod, guild);
|
||||||
|
|
||||||
@@ -88,14 +93,6 @@ export class StageHostCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Event coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,16 +112,16 @@ export class StageHostCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const stageHost = guild.roles.cache.get(IDs.roles.stageHost);
|
const stageHost = await getRole(IDs.roles.stageHost, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stageHost === undefined) {
|
if (!isRole(stageHost)) {
|
||||||
info.message = 'Error fetching stage host role from cache!';
|
info.message = 'Error fetching stage host role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class TrialModCommand extends Command {
|
export class TrialModCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'trialmod',
|
name: 'trialmod',
|
||||||
@@ -63,13 +66,15 @@ export class TrialModCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageMod(user, mod, guild);
|
const info = await this.manageMod(user, mod, guild);
|
||||||
|
|
||||||
@@ -89,14 +94,6 @@ export class TrialModCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Mod coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -116,16 +113,16 @@ export class TrialModCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const moderator = guild.roles.cache.get(IDs.roles.staff.trialModerator);
|
const moderator = await getRole(IDs.roles.staff.trialModerator, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moderator === undefined) {
|
if (!isRole(moderator)) {
|
||||||
info.message = 'Error fetching the trial moderator role from cache!';
|
info.message = 'Error fetching the trial moderator role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class TrialVerifierCommand extends Command {
|
export class TrialVerifierCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'trialverifier',
|
name: 'trialverifier',
|
||||||
@@ -62,13 +65,15 @@ export class TrialVerifierCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageTrialVerifier(user, mod, guild);
|
const info = await this.manageTrialVerifier(user, mod, guild);
|
||||||
|
|
||||||
@@ -88,14 +93,6 @@ export class TrialVerifierCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Verifier coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,16 +112,16 @@ export class TrialVerifierCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const trialVerifier = guild.roles.cache.get(IDs.roles.staff.trialVerifier);
|
const trialVerifier = await getRole(IDs.roles.staff.trialVerifier, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trialVerifier === undefined) {
|
if (!isRole(trialVerifier)) {
|
||||||
info.message = 'Error fetching the trial verifier role from cache!';
|
info.message = 'Error fetching the trial verifier role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class VerifierCommand extends Command {
|
export class VerifierCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'verifier',
|
name: 'verifier',
|
||||||
@@ -62,13 +65,15 @@ export class VerifierCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageVerifier(user, mod, guild);
|
const info = await this.manageVerifier(user, mod, guild);
|
||||||
|
|
||||||
@@ -88,14 +93,6 @@ export class VerifierCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Verifier coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,16 +112,16 @@ export class VerifierCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const verifier = guild.roles.cache.get(IDs.roles.staff.verifier);
|
const verifier = await getRole(IDs.roles.staff.verifier, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verifier === undefined) {
|
if (!isRole(verifier)) {
|
||||||
info.message = 'Error fetching verifier role from cache!';
|
info.message = 'Error fetching verifier role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class ActivistCommand extends Command {
|
export class ActivistCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'activist',
|
name: 'activist',
|
||||||
@@ -65,13 +68,15 @@ export class ActivistCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageActivist(user, mod, guild);
|
const info = await this.manageActivist(user, mod, guild);
|
||||||
|
|
||||||
@@ -91,12 +96,6 @@ export class ActivistCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Staff not found! Try again or contact a developer!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -116,22 +115,22 @@ export class ActivistCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const modMember = guild.members.cache.get(mod.id);
|
const modMember = await getGuildMember(mod.id, guild);
|
||||||
const activist = guild.roles.cache.get(IDs.roles.vegan.activist);
|
const activist = await getRole(IDs.roles.vegan.activist, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modMember === undefined) {
|
if (!isGuildMember(modMember)) {
|
||||||
info.message = "Error fetching the staff's guild member!";
|
info.message = "Error fetching the staff's guild member!";
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activist === undefined) {
|
if (!isRole(activist)) {
|
||||||
info.message = 'Error fetching activist role from cache!';
|
info.message = 'Error fetching activist role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class ARAVeganCommand extends Command {
|
export class ARAVeganCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'aravegan',
|
name: 'aravegan',
|
||||||
@@ -64,13 +67,15 @@ export class ARAVeganCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageVegan(user, mod, guild);
|
const info = await this.manageVegan(user, mod, guild);
|
||||||
|
|
||||||
@@ -90,12 +95,6 @@ export class ARAVeganCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Staff not found! Try again or contact a developer!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,22 +114,22 @@ export class ARAVeganCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const modMember = guild.members.cache.get(mod.id);
|
const modMember = await getGuildMember(mod.id, guild);
|
||||||
const vegan = guild.roles.cache.get(IDs.roles.vegan.araVegan);
|
const vegan = await getRole(IDs.roles.vegan.araVegan, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modMember === undefined) {
|
if (!isGuildMember(modMember)) {
|
||||||
info.message = "Error fetching the staff's guild member!";
|
info.message = "Error fetching the staff's guild member!";
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vegan === undefined) {
|
if (!isRole(vegan)) {
|
||||||
info.message = 'Error fetching vegan role from cache!';
|
info.message = 'Error fetching vegan role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class ConvincedCommand extends Command {
|
export class ConvincedCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'convinced',
|
name: 'convinced',
|
||||||
@@ -63,13 +66,15 @@ export class ConvincedCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageConvinced(user, mod, guild);
|
const info = await this.manageConvinced(user, mod, guild);
|
||||||
|
|
||||||
@@ -89,12 +94,6 @@ export class ConvincedCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Mod not found! Try again or contact a developer!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -114,16 +113,16 @@ export class ConvincedCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const convinced = guild.roles.cache.get(IDs.roles.nonvegan.convinced);
|
const convinced = await getRole(IDs.roles.nonvegan.convinced, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (convinced === undefined) {
|
if (!isRole(convinced)) {
|
||||||
info.message = 'Error fetching coordinator role from cache!';
|
info.message = 'Error fetching coordinator role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,18 +18,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class PlusCommand extends Command {
|
export class PlusCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'plus',
|
name: 'plus',
|
||||||
aliases: ['+'],
|
aliases: ['+'],
|
||||||
description: 'Give/remove the plus role',
|
description: 'Give/remove the plus role',
|
||||||
preconditions: [['CoordinatorOnly', 'ModOnly']],
|
preconditions: [['CoordinatorOnly', 'VerifierOnly', 'ModOnly']],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +66,7 @@ export class PlusCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -88,14 +91,6 @@ export class PlusCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply(
|
|
||||||
'Coordinator not found! Try again or contact a developer!',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -115,16 +110,16 @@ export class PlusCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const plus = guild.roles.cache.get(IDs.roles.vegan.plus);
|
const plus = await getRole(IDs.roles.vegan.plus, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plus === undefined) {
|
if (!isRole(plus)) {
|
||||||
info.message = 'Error fetching plus role from cache!';
|
info.message = 'Error fetching plus role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -138,6 +133,14 @@ export class PlusCommand extends Command {
|
|||||||
info.success = true;
|
info.success = true;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if the user is vegan before giving the plus role
|
||||||
|
// If not, stop from giving the plus role
|
||||||
|
if (!member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
||||||
|
info.message = `Can't give ${user} the vegan role as they are not vegan!`;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
// Add Plus role to the user
|
// Add Plus role to the user
|
||||||
await member.roles.add(plus);
|
await member.roles.add(plus);
|
||||||
await roleAddLog(user.id, mod.id, plus);
|
await roleAddLog(user.id, mod.id, plus);
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class TrustedCommand extends Command {
|
export class TrustedCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'trusted',
|
name: 'trusted',
|
||||||
@@ -63,13 +66,15 @@ export class TrustedCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageTrusted(user, mod, guild);
|
const info = await this.manageTrusted(user, mod, guild);
|
||||||
|
|
||||||
@@ -89,12 +94,6 @@ export class TrustedCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Mod not found! Try again or contact a developer!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -114,16 +113,16 @@ export class TrustedCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const trusted = guild.roles.cache.get(IDs.roles.trusted);
|
const trusted = await getRole(IDs.roles.trusted, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trusted === undefined) {
|
if (!isRole(trusted)) {
|
||||||
info.message = 'Error fetching trusted role from cache!';
|
info.message = 'Error fetching trusted role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -146,8 +145,8 @@ export class TrustedCommand extends Command {
|
|||||||
.send(
|
.send(
|
||||||
`You have been given the ${trusted.name} role by ${mod}!` +
|
`You have been given the ${trusted.name} role by ${mod}!` +
|
||||||
'\n\nThis role allows you to post attachments to the server and stream in VCs.' +
|
'\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." +
|
'\nMake sure that you follow the rules, especially by **not** posting anything **NSFW**, and **no animal products or consumption of animal products**.' +
|
||||||
`\nNot following these rules can result in the removal of the ${trusted.name} role.`,
|
`\n\nNot following these rules will result in the **immediate removal** of the ${trusted.name} role.`,
|
||||||
)
|
)
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
info.success = true;
|
info.success = true;
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class VeganCommand extends Command {
|
export class VeganCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'vegan',
|
name: 'vegan',
|
||||||
@@ -65,13 +68,15 @@ export class VeganCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageVegan(user, mod, guild);
|
const info = await this.manageVegan(user, mod, guild);
|
||||||
|
|
||||||
@@ -91,12 +96,6 @@ export class VeganCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Staff not found! Try again or contact a developer!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -116,22 +115,22 @@ export class VeganCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const modMember = guild.members.cache.get(mod.id);
|
const modMember = await getGuildMember(mod.id, guild);
|
||||||
const vegan = guild.roles.cache.get(IDs.roles.vegan.vegan);
|
const vegan = await getRole(IDs.roles.vegan.vegan, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modMember === undefined) {
|
if (!isGuildMember(modMember)) {
|
||||||
info.message = "Error fetching the staff's guild member!";
|
info.message = "Error fetching the staff's guild member!";
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vegan === undefined) {
|
if (!isRole(vegan)) {
|
||||||
info.message = 'Error fetching vegan role from cache!';
|
info.message = 'Error fetching vegan role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Guild, User, Message } from 'discord.js';
|
import { Guild, User, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
import { roleAddLog, roleRemoveLog } from '#utils/logging/role';
|
||||||
|
import { getGuildMember, getRole } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class VegCuriousCommand extends Command {
|
export class VegCuriousCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'vegcurious',
|
name: 'vegcurious',
|
||||||
@@ -63,13 +66,15 @@ export class VegCuriousCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
const info = await this.manageVegCurious(user, mod, guild);
|
const info = await this.manageVegCurious(user, mod, guild);
|
||||||
|
|
||||||
@@ -89,12 +94,6 @@ export class VegCuriousCommand extends Command {
|
|||||||
|
|
||||||
const mod = message.author;
|
const mod = message.author;
|
||||||
|
|
||||||
if (mod === null) {
|
|
||||||
await message.react('❌');
|
|
||||||
await message.reply('Staff not found! Try again or contact a developer!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { guild } = message;
|
const { guild } = message;
|
||||||
|
|
||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
@@ -114,22 +113,22 @@ export class VegCuriousCommand extends Command {
|
|||||||
message: '',
|
message: '',
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
const member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
const modMember = guild.members.cache.get(mod.id);
|
const modMember = await getGuildMember(mod.id, guild);
|
||||||
const vegCurious = guild.roles.cache.get(IDs.roles.nonvegan.vegCurious);
|
const vegCurious = await getRole(IDs.roles.nonvegan.vegCurious, guild);
|
||||||
|
|
||||||
// Checks if user's GuildMember was found in cache
|
// Checks if user's GuildMember was found in cache
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
info.message = 'Error fetching guild member for the user!';
|
info.message = 'Error fetching guild member for the user!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modMember === undefined) {
|
if (!isGuildMember(modMember)) {
|
||||||
info.message = "Error fetching the staff's guild member!";
|
info.message = "Error fetching the staff's guild member!";
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vegCurious === undefined) {
|
if (!isRole(vegCurious)) {
|
||||||
info.message = 'Error fetching veg curious role from cache!';
|
info.message = 'Error fetching veg curious role from cache!';
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Message } from 'discord.js';
|
import { Message, MessageFlagsBitField } from 'discord.js';
|
||||||
|
|
||||||
export class ApplyCommand extends Command {
|
export class ApplyCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'apply',
|
name: 'apply',
|
||||||
@@ -47,8 +47,8 @@ export class ApplyCommand extends Command {
|
|||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: this.message,
|
content: this.message,
|
||||||
fetchReply: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
ephemeral: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Message } from 'discord.js';
|
import { Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getRole } from '#utils/fetcher';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class RenameUserCommand extends Command {
|
export class RenameUserCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'count',
|
name: 'count',
|
||||||
@@ -47,22 +49,22 @@ export class RenameUserCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await guild.members.fetch();
|
await guild.members.fetch();
|
||||||
|
|
||||||
const vegan = await guild.roles.cache.get(IDs.roles.vegan.vegan);
|
const vegan = await getRole(IDs.roles.vegan.vegan, guild);
|
||||||
const notVegan = await guild.roles.cache.get(IDs.roles.nonvegan.nonvegan);
|
const notVegan = await getRole(IDs.roles.nonvegan.nonvegan, guild);
|
||||||
|
|
||||||
if (vegan === undefined || notVegan === undefined) {
|
if (!isRole(vegan) || !isRole(notVegan)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching roles!',
|
content: 'Error fetching roles!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -71,7 +73,7 @@ export class RenameUserCommand extends Command {
|
|||||||
content:
|
content:
|
||||||
`${vegan.name}s: \`${vegan.members.size}\`` +
|
`${vegan.name}s: \`${vegan.members.size}\`` +
|
||||||
`\n${notVegan.name}s: \`${notVegan.members.size}\``,
|
`\n${notVegan.name}s: \`${notVegan.members.size}\``,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,8 +90,8 @@ export class RenameUserCommand extends Command {
|
|||||||
|
|
||||||
await guild.members.fetch();
|
await guild.members.fetch();
|
||||||
|
|
||||||
const vegan = await guild.roles.cache.get(IDs.roles.vegan.vegan);
|
const vegan = guild.roles.cache.get(IDs.roles.vegan.vegan);
|
||||||
const notVegan = await guild.roles.cache.get(IDs.roles.nonvegan.nonvegan);
|
const notVegan = guild.roles.cache.get(IDs.roles.nonvegan.nonvegan);
|
||||||
|
|
||||||
if (vegan === undefined || notVegan === undefined) {
|
if (vegan === undefined || notVegan === undefined) {
|
||||||
await message.react('❌');
|
await message.react('❌');
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { EmbedBuilder } from 'discord.js';
|
|||||||
import type { Message } from 'discord.js';
|
import type { Message } from 'discord.js';
|
||||||
|
|
||||||
export class HelpCommand extends Command {
|
export class HelpCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'help',
|
name: 'help',
|
||||||
|
|||||||
@@ -18,9 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
|
import IDs from '#utils/ids';
|
||||||
|
import { MessageFlagsBitField } from 'discord.js';
|
||||||
|
|
||||||
export class InfoCommand extends Command {
|
export class InfoCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'info',
|
name: 'info',
|
||||||
@@ -65,11 +67,7 @@ export class InfoCommand extends Command {
|
|||||||
const option = interaction.options.getString('info', true);
|
const option = interaction.options.getString('info', true);
|
||||||
let ephemeral = interaction.options.getBoolean('visible');
|
let ephemeral = interaction.options.getBoolean('visible');
|
||||||
|
|
||||||
if (ephemeral === null) {
|
ephemeral = ephemeral !== true;
|
||||||
ephemeral = true;
|
|
||||||
} else {
|
|
||||||
ephemeral = !ephemeral;
|
|
||||||
}
|
|
||||||
|
|
||||||
let message: string;
|
let message: string;
|
||||||
|
|
||||||
@@ -94,7 +92,9 @@ export class InfoCommand extends Command {
|
|||||||
message =
|
message =
|
||||||
"If you want to have the vegan or activist role, you'll need to do a voice verification. " +
|
"If you want to have the vegan or activist role, you'll need to do a voice verification. " +
|
||||||
"To do this, hop into the 'Verification' voice channel." +
|
"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.";
|
"\n\nIf there aren't any verifiers available, you'll be disconnected, and you can rejoin later." +
|
||||||
|
`\n\nAlternatively if you would like text verification, you can use \`/apply\` in <#${IDs.channels.nonVegan.vcText}> ` +
|
||||||
|
'to be able fill out a Vegan Verification form through the Appy Bot.';
|
||||||
break;
|
break;
|
||||||
case 'modMail':
|
case 'modMail':
|
||||||
message =
|
message =
|
||||||
@@ -112,7 +112,7 @@ export class InfoCommand extends Command {
|
|||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: message,
|
content: message,
|
||||||
ephemeral,
|
flags: ephemeral ? MessageFlagsBitField.Flags.Ephemeral : undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,11 @@
|
|||||||
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 { isMessageInstance } from '@sapphire/discord.js-utilities';
|
|
||||||
import { Command } from '@sapphire/framework';
|
import { Command } from '@sapphire/framework';
|
||||||
import type { Message } from 'discord.js';
|
import { Message, MessageFlagsBitField } from 'discord.js';
|
||||||
|
|
||||||
export class PingCommand extends Command {
|
export class PingCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'ping',
|
name: 'ping',
|
||||||
@@ -41,12 +40,13 @@ export class PingCommand extends Command {
|
|||||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||||
const msg = await interaction.reply({
|
const msg = await interaction.reply({
|
||||||
content: 'Ping?',
|
content: 'Ping?',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isMessageInstance(msg)) {
|
if (msg.resource !== null && msg.resource.message !== null) {
|
||||||
const diff = msg.createdTimestamp - interaction.createdTimestamp;
|
const diff =
|
||||||
|
msg.resource.message.createdTimestamp - interaction.createdTimestamp;
|
||||||
const ping = Math.round(this.container.client.ws.ping);
|
const ping = Math.round(this.container.client.ws.ping);
|
||||||
return interaction.editReply(
|
return interaction.editReply(
|
||||||
`Pong 🏓! (Round trip took: ${diff}ms. Heartbeat: ${ping}ms.)`,
|
`Pong 🏓! (Round trip took: ${diff}ms. Heartbeat: ${ping}ms.)`,
|
||||||
@@ -57,6 +57,11 @@ export class PingCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async messageRun(message: Message) {
|
public async messageRun(message: Message) {
|
||||||
|
if (!message.channel.isSendable()) {
|
||||||
|
// TODO manage logging/errors properly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const msg = await message.channel.send('Ping?');
|
const msg = await message.channel.send('Ping?');
|
||||||
|
|
||||||
const diff = msg.createdTimestamp - message.createdTimestamp;
|
const diff = msg.createdTimestamp - message.createdTimestamp;
|
||||||
|
|||||||
@@ -18,16 +18,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { Message, User, Guild, Snowflake } from 'discord.js';
|
import {
|
||||||
|
Message,
|
||||||
|
User,
|
||||||
|
Guild,
|
||||||
|
Snowflake,
|
||||||
|
MessageFlagsBitField,
|
||||||
|
} from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import {
|
import {
|
||||||
finishVerifyMessages,
|
finishVerifyMessages,
|
||||||
giveVerificationRoles,
|
giveVerificationRoles,
|
||||||
} from '#utils/verification';
|
} from '#utils/verification';
|
||||||
import { manualVerification } from '#utils/database/verification';
|
import { manualVerification } from '#utils/database/verification';
|
||||||
|
import { getGuildMember } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class VerifyCommand extends Command {
|
export class VerifyCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'verify',
|
name: 'verify',
|
||||||
@@ -77,8 +85,8 @@ export class VerifyCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -93,7 +101,7 @@ export class VerifyCommand extends Command {
|
|||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: verify.message,
|
content: verify.message,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,15 +167,12 @@ export class VerifyCommand extends Command {
|
|||||||
convinced: false,
|
convinced: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
// Checks if member is null
|
// Checks if member is null
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
member = await guild.members.fetch(user.id).catch(() => undefined);
|
info.message = 'Failed to fetch member';
|
||||||
if (member === undefined) {
|
return info;
|
||||||
info.message = 'Failed to fetch member';
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (member.roles.cache.hasAny(...IDs.roles.restrictions.restricted)) {
|
if (member.roles.cache.hasAny(...IDs.roles.restrictions.restricted)) {
|
||||||
@@ -175,15 +180,12 @@ export class VerifyCommand extends Command {
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
let verifier = guild.members.cache.get(verifierId);
|
const verifier = await getGuildMember(verifierId, guild);
|
||||||
|
|
||||||
// Checks if verifier is null
|
// Checks if verifier is null
|
||||||
if (verifier === undefined) {
|
if (!isGuildMember(verifier)) {
|
||||||
verifier = await guild.members.fetch(user.id).catch(() => undefined);
|
info.message = 'Failed to fetch verifier';
|
||||||
if (verifier === undefined) {
|
return info;
|
||||||
info.message = 'Failed to fetch verifier';
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const roleArgs = rolesString.split(' ');
|
const roleArgs = rolesString.split(' ');
|
||||||
|
|||||||
@@ -20,9 +20,12 @@
|
|||||||
import { Command, RegisterBehavior } from '@sapphire/framework';
|
import { Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { checkVerificationFinish } from '#utils/database/verification';
|
import { checkVerificationFinish } from '#utils/database/verification';
|
||||||
|
import { MessageFlagsBitField } from 'discord.js';
|
||||||
|
import { getGuildMember } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class VerifyTimeoutRemoveCommand extends Command {
|
export class VerifyTimeoutRemoveCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'verifytimeoutremove',
|
name: 'verifytimeoutremove',
|
||||||
@@ -60,22 +63,21 @@ export class VerifyTimeoutRemoveCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Error fetching guild!',
|
content: 'Error fetching guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
fetchReply: true,
|
withResponse: true,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
let member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
member = await guild.members.fetch(user.id).catch(undefined);
|
await interaction.editReply(`${user} is not on this server!`);
|
||||||
if (member === undefined) {
|
return;
|
||||||
await interaction.editReply(`${user} is not on this server!`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!member.roles.cache.has(IDs.roles.verifyBlock)) {
|
if (!member.roles.cache.has(IDs.roles.verifyBlock)) {
|
||||||
|
|||||||
@@ -18,12 +18,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
import { Args, Command, RegisterBehavior } from '@sapphire/framework';
|
||||||
import type { User, Guild, Message } from 'discord.js';
|
import { User, Guild, Message, MessageFlagsBitField } from 'discord.js';
|
||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
import { getRank, xpToNextLevel } from '#utils/database/xp';
|
import { getRank, xpToNextLevel } from '#utils/database/fun/xp';
|
||||||
|
import { getGuildMember } from '#utils/fetcher';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class RankCommand extends Command {
|
export class RankCommand extends Command {
|
||||||
public constructor(context: Command.Context, options: Command.Options) {
|
public constructor(context: Command.LoaderContext, options: Command.Options) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
name: 'rank',
|
name: 'rank',
|
||||||
@@ -55,7 +57,7 @@ export class RankCommand extends Command {
|
|||||||
if (guild === null) {
|
if (guild === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'Could not find the guild!',
|
content: 'Could not find the guild!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -108,14 +110,11 @@ export class RankCommand extends Command {
|
|||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let member = guild.members.cache.get(user.id);
|
const member = await getGuildMember(user.id, guild);
|
||||||
|
|
||||||
if (member === undefined) {
|
if (!isGuildMember(member)) {
|
||||||
member = await guild.members.fetch(user.id).catch(() => undefined);
|
info.message = 'The user is not on this server!';
|
||||||
if (member === undefined) {
|
return info;
|
||||||
info.message = 'The user is not on this server!';
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rank = await getRank(user.id);
|
const rank = await getRank(user.id);
|
||||||
|
|||||||
25
src/index.ts
25
src/index.ts
@@ -25,8 +25,11 @@ import { LogLevel, SapphireClient, container } from '@sapphire/framework';
|
|||||||
import '@sapphire/plugin-scheduled-tasks/register';
|
import '@sapphire/plugin-scheduled-tasks/register';
|
||||||
import '@sapphire/plugin-logger/register';
|
import '@sapphire/plugin-logger/register';
|
||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
import { createClient } from 'redis';
|
import { Redis } from 'ioredis';
|
||||||
import type { RedisClientType } from 'redis';
|
|
||||||
|
const REDIS_PORT = process.env.REDIS_PORT
|
||||||
|
? parseInt(process.env.REDIS_PORT)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
// Setting up the Sapphire client
|
// Setting up the Sapphire client
|
||||||
const client = new SapphireClient({
|
const client = new SapphireClient({
|
||||||
@@ -50,7 +53,10 @@ const client = new SapphireClient({
|
|||||||
tasks: {
|
tasks: {
|
||||||
bull: {
|
bull: {
|
||||||
connection: {
|
connection: {
|
||||||
host: process.env.BULLMQ_URL,
|
host: process.env.REDIS_HOST,
|
||||||
|
username: process.env.REDIS_USER,
|
||||||
|
password: process.env.REDIS_PASSWORD,
|
||||||
|
port: REDIS_PORT,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -63,11 +69,14 @@ const main = async () => {
|
|||||||
client.logger.info('Logging in');
|
client.logger.info('Logging in');
|
||||||
|
|
||||||
// Create databases
|
// Create databases
|
||||||
container.database = await new PrismaClient();
|
container.database = new PrismaClient();
|
||||||
container.redis = createClient({
|
container.redis = new Redis({
|
||||||
url: process.env.REDIS_URL,
|
host: process.env.REDIS_HOST,
|
||||||
|
username: process.env.REDIS_USER,
|
||||||
|
password: process.env.REDIS_PASSWORD,
|
||||||
|
port: REDIS_PORT,
|
||||||
|
db: 1,
|
||||||
});
|
});
|
||||||
await container.redis.connect();
|
|
||||||
|
|
||||||
// Log the bot in to Discord
|
// Log the bot in to Discord
|
||||||
await client.login(token);
|
await client.login(token);
|
||||||
@@ -83,7 +92,7 @@ const main = async () => {
|
|||||||
declare module '@sapphire/pieces' {
|
declare module '@sapphire/pieces' {
|
||||||
interface Container {
|
interface Container {
|
||||||
database: PrismaClient;
|
database: PrismaClient;
|
||||||
redis: RedisClientType;
|
redis: Redis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,15 @@ import {
|
|||||||
InteractionHandler,
|
InteractionHandler,
|
||||||
InteractionHandlerTypes,
|
InteractionHandlerTypes,
|
||||||
} from '@sapphire/framework';
|
} from '@sapphire/framework';
|
||||||
import type { PieceContext } from '@sapphire/framework';
|
import { ButtonInteraction, MessageFlagsBitField } from 'discord.js';
|
||||||
import type { ButtonInteraction, GuildMember } from 'discord.js';
|
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class NonVeganAccessButtonHandler extends InteractionHandler {
|
export class NonVeganAccessButtonHandler extends InteractionHandler {
|
||||||
public constructor(ctx: PieceContext, options: InteractionHandler.Options) {
|
public constructor(
|
||||||
|
ctx: InteractionHandler.LoaderContext,
|
||||||
|
options: InteractionHandler.Options,
|
||||||
|
) {
|
||||||
super(ctx, {
|
super(ctx, {
|
||||||
...options,
|
...options,
|
||||||
interactionHandlerType: InteractionHandlerTypes.Button,
|
interactionHandlerType: InteractionHandlerTypes.Button,
|
||||||
@@ -40,54 +43,42 @@ export class NonVeganAccessButtonHandler extends InteractionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async run(interaction: ButtonInteraction) {
|
public async run(interaction: ButtonInteraction) {
|
||||||
let { member } = interaction;
|
const { member } = interaction;
|
||||||
|
|
||||||
const errorMessage =
|
const errorMessage =
|
||||||
'There was an error giving you the role, please try again later or contact ModMail/the developer ' +
|
'There was an error giving you the role, please try again later or contact ModMail/the developer ' +
|
||||||
'to sort out this problem.';
|
'to sort out this problem.';
|
||||||
|
|
||||||
if (member === null) {
|
if (!isGuildMember(member)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: errorMessage,
|
content: errorMessage,
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (!member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
||||||
member = member as GuildMember;
|
await interaction.reply({
|
||||||
|
content: 'You need to be vegan to use this button!',
|
||||||
if (!member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
await interaction.reply({
|
});
|
||||||
content: 'You need to be vegan to use this button!',
|
return;
|
||||||
ephemeral: true,
|
} else if (member.roles.cache.has(IDs.roles.vegan.nvAccess)) {
|
||||||
});
|
await member.roles.remove(IDs.roles.vegan.nvAccess);
|
||||||
return;
|
await interaction.reply({
|
||||||
}
|
content:
|
||||||
|
'Your access from the non vegan section has been removed. ' +
|
||||||
if (member.roles.cache.has(IDs.roles.vegan.nvAccess)) {
|
'If you want to gain access again, click this button again.',
|
||||||
await member.roles.remove(IDs.roles.vegan.nvAccess);
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
await interaction.reply({
|
});
|
||||||
content:
|
return;
|
||||||
'Your access from the non vegan section has been removed. ' +
|
} else {
|
||||||
'If you want to gain access again, click this button again.',
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await member.roles.add(IDs.roles.vegan.nvAccess);
|
await member.roles.add(IDs.roles.vegan.nvAccess);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content:
|
content:
|
||||||
'Your access to the non vegan section has been given back. ' +
|
'Your access to the non vegan section has been given back. ' +
|
||||||
'If you want to remove access again, click this button again.',
|
'If you want to remove access again, click this button again.',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
this.container.logger.error(`Non Vegan Access Interaction: ${error}`);
|
|
||||||
await interaction.reply({
|
|
||||||
content: errorMessage,
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,12 +21,18 @@ import {
|
|||||||
InteractionHandler,
|
InteractionHandler,
|
||||||
InteractionHandlerTypes,
|
InteractionHandlerTypes,
|
||||||
} from '@sapphire/framework';
|
} from '@sapphire/framework';
|
||||||
import type { PieceContext } from '@sapphire/framework';
|
import { ButtonInteraction, MessageFlagsBitField } from 'discord.js';
|
||||||
import type { ButtonInteraction, GuildMember, TextChannel } from 'discord.js';
|
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { checkActive } from '#utils/database/moderation/restriction';
|
||||||
|
import { addUser } from '#utils/database/dbExistingUser';
|
||||||
|
import { getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import { isGuildMember, isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class WelcomeButtonHandler extends InteractionHandler {
|
export class WelcomeButtonHandler extends InteractionHandler {
|
||||||
public constructor(ctx: PieceContext, options: InteractionHandler.Options) {
|
public constructor(
|
||||||
|
ctx: InteractionHandler.LoaderContext,
|
||||||
|
options: InteractionHandler.Options,
|
||||||
|
) {
|
||||||
super(ctx, {
|
super(ctx, {
|
||||||
...options,
|
...options,
|
||||||
interactionHandlerType: InteractionHandlerTypes.Button,
|
interactionHandlerType: InteractionHandlerTypes.Button,
|
||||||
@@ -40,49 +46,88 @@ export class WelcomeButtonHandler extends InteractionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async run(interaction: ButtonInteraction) {
|
public async run(interaction: ButtonInteraction) {
|
||||||
let { member } = interaction;
|
const { member } = interaction;
|
||||||
const general = this.container.client.channels.cache.get(
|
const general = await getTextBasedChannel(IDs.channels.nonVegan.general);
|
||||||
IDs.channels.nonVegan.general,
|
|
||||||
) as TextChannel | undefined;
|
|
||||||
if (general === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (member === null) {
|
// Messages that are used multiple times
|
||||||
|
const roleErrorMessage =
|
||||||
|
'There was an error giving you the role, please try again later or contact ModMail to be let into this server.';
|
||||||
|
const welcomeMessage =
|
||||||
|
`${member} Welcome to ARA! :D Please check <#${IDs.channels.information.roles}> ` +
|
||||||
|
`and remember to follow the <#${IDs.channels.information.conduct}> and to respect ongoing discussions and debates.` +
|
||||||
|
`\n\nIf you are vegan, you can join the 'Verification' voice channel, or use \`/apply\` with the Appy bot in <#${IDs.channels.nonVegan.vcText}>, ` +
|
||||||
|
'to be verified and gain access to more channels.';
|
||||||
|
|
||||||
|
// Checks if general is not in the cache
|
||||||
|
if (!isTextChannel(general)) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'WelcomeButtonHandler: Could not find and fetch the general channel!',
|
||||||
|
);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content:
|
content:
|
||||||
'There was an error giving you the role, please try again later or contact ModMail to be let into this server.',
|
'Sorry there was a problem trying to give you access to the server. Please try again later.',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// If the member could not be found
|
||||||
member = member as GuildMember;
|
if (!isGuildMember(member)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: roleErrorMessage,
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
// Give non-vegan role
|
return;
|
||||||
if (!member.voice.channel) {
|
}
|
||||||
await member.roles.add(IDs.roles.nonvegan.nonvegan);
|
|
||||||
|
|
||||||
await general.send(
|
// Checks if the user is currently restricted
|
||||||
`${member} Welcome to ARA! :D Please check <#${IDs.channels.information.roles}> ` +
|
if (await checkActive(member.id)) {
|
||||||
`and remember to follow the <#${IDs.channels.information.conduct}> and to respect ongoing discussion and debates.` +
|
await interaction.reply({
|
||||||
"\n\nIf you would like to be verified as a vegan, join the 'Verification' voice channel.",
|
content: `You are currently restricted from this server! Contact the moderators by sending a DM to <@${IDs.modMail}>.`,
|
||||||
);
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give non-vegan role
|
||||||
|
if (member.voice.channel) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content:
|
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.",
|
"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,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the user to the database
|
||||||
|
await addUser(member.id);
|
||||||
|
|
||||||
|
// Give the role to the member
|
||||||
|
const role = await member.roles
|
||||||
|
.add(IDs.roles.nonvegan.nonvegan)
|
||||||
|
.catch(() => undefined);
|
||||||
|
|
||||||
|
// If the role could not be given
|
||||||
|
if (role === undefined) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content:
|
content: roleErrorMessage,
|
||||||
'There was an error giving you the role, please try again later or contact ModMail to be let into this server.',
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
ephemeral: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (general.isSendable()) {
|
||||||
|
await general.send(welcomeMessage);
|
||||||
|
} else {
|
||||||
|
this.container.logger.error(
|
||||||
|
'WelcomeButtonHandler: The bot does not have permission to send in general!',
|
||||||
|
);
|
||||||
|
await member.send(welcomeMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,18 @@
|
|||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type { GuildBan } from 'discord.js';
|
import type { GuildBan } from 'discord.js';
|
||||||
import { AuditLogEvent, EmbedBuilder, TextChannel } from 'discord.js';
|
import { AuditLogEvent, EmbedBuilder } from 'discord.js';
|
||||||
import { addBan, checkBan } from '#utils/database/ban';
|
import { addBan, checkBan } from '#utils/database/moderation/ban';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { addEmptyUser, addExistingUser } from '#utils/database/dbExistingUser';
|
import { addEmptyUser, addExistingUser } from '#utils/database/dbExistingUser';
|
||||||
|
import { getGuildMember, getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import { isGuildMember, isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class BanListener extends Listener {
|
export class BanListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'guildBanAdd',
|
event: 'guildBanAdd',
|
||||||
@@ -79,17 +84,12 @@ export class BanListener extends Listener {
|
|||||||
const { guild } = ban;
|
const { guild } = ban;
|
||||||
|
|
||||||
// Gets mod's GuildMember
|
// Gets mod's GuildMember
|
||||||
let mod = guild.members.cache.get(executor.id);
|
const mod = await getGuildMember(executor.id, guild);
|
||||||
|
|
||||||
// Checks if GuildMember is null
|
// Checks if GuildMember is null
|
||||||
if (mod === undefined) {
|
if (!isGuildMember(mod)) {
|
||||||
mod = await guild.members.fetch(executor.id).catch(() => undefined);
|
this.container.logger.error('UnbanListener: Could not fetch moderator.');
|
||||||
if (mod === undefined) {
|
return;
|
||||||
this.container.logger.error(
|
|
||||||
'UnbanListener: Could not fetch moderator.',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if mod is in database
|
// Check if mod is in database
|
||||||
@@ -115,18 +115,11 @@ 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.get(IDs.channels.logs.restricted) as
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.restricted);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (logChannel === undefined) {
|
if (!isTextChannel(logChannel)) {
|
||||||
logChannel = (await guild.channels.fetch(
|
this.container.logger.error('BanListener: Could not fetch log channel');
|
||||||
IDs.channels.logs.restricted,
|
return;
|
||||||
)) as TextChannel | undefined;
|
|
||||||
if (logChannel === undefined) {
|
|
||||||
this.container.logger.error('BanListener: Could not fetch log channel');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const log = new EmbedBuilder()
|
const log = new EmbedBuilder()
|
||||||
|
|||||||
@@ -19,11 +19,14 @@
|
|||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type { GuildMember } from 'discord.js';
|
import type { GuildMember } from 'discord.js';
|
||||||
import { checkBan, getBanReason } from '#utils/database/ban';
|
import { checkBan, getBanReason } from '#utils/database/moderation/ban';
|
||||||
import { checkTempBan } from '#utils/database/tempBan';
|
import { checkTempBan } from '#utils/database/moderation/tempBan';
|
||||||
|
|
||||||
export class BanJoinListener extends Listener {
|
export class BanJoinListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'guildMemberAdd',
|
event: 'guildMemberAdd',
|
||||||
|
|||||||
@@ -19,13 +19,18 @@
|
|||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type { GuildBan } from 'discord.js';
|
import type { GuildBan } from 'discord.js';
|
||||||
import { AuditLogEvent, EmbedBuilder, TextChannel } from 'discord.js';
|
import { AuditLogEvent, EmbedBuilder } from 'discord.js';
|
||||||
import { addBan, checkBan, removeBan } from '#utils/database/ban';
|
import { addBan, checkBan, removeBan } from '#utils/database/moderation/ban';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { addEmptyUser, addExistingUser } from '#utils/database/dbExistingUser';
|
import { addEmptyUser, addExistingUser } from '#utils/database/dbExistingUser';
|
||||||
|
import { getGuildMember, getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import { isTextBasedChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class UnbanListener extends Listener {
|
export class UnbanListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'guildBanRemove',
|
event: 'guildBanRemove',
|
||||||
@@ -68,17 +73,12 @@ export class UnbanListener extends Listener {
|
|||||||
const { guild } = ban;
|
const { guild } = ban;
|
||||||
|
|
||||||
// Gets mod's GuildMember
|
// Gets mod's GuildMember
|
||||||
let mod = guild.members.cache.get(executor.id);
|
const mod = await getGuildMember(executor.id, guild);
|
||||||
|
|
||||||
// Checks if GuildMember is null
|
// Checks if GuildMember is null
|
||||||
if (mod === undefined) {
|
if (mod === undefined) {
|
||||||
mod = await guild.members.fetch(executor.id).catch(() => undefined);
|
this.container.logger.error('UnbanListener: Could not fetch moderator.');
|
||||||
if (mod === undefined) {
|
return;
|
||||||
this.container.logger.error(
|
|
||||||
'UnbanListener: Could not fetch moderator.',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if mod is in database
|
// Check if mod is in database
|
||||||
@@ -97,20 +97,11 @@ 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.get(IDs.channels.logs.restricted) as
|
const logChannel = await getTextBasedChannel(IDs.channels.logs.restricted);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (logChannel === undefined) {
|
if (!isTextBasedChannel(logChannel)) {
|
||||||
logChannel = (await guild.channels.fetch(
|
this.container.logger.error('UnbanListener: Could not fetch log channel');
|
||||||
IDs.channels.logs.restricted,
|
return;
|
||||||
)) as TextChannel | undefined;
|
|
||||||
if (logChannel === undefined) {
|
|
||||||
this.container.logger.error(
|
|
||||||
'UnbanListener: Could not fetch log channel',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const log = new EmbedBuilder()
|
const log = new EmbedBuilder()
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ import { Listener } from '@sapphire/framework';
|
|||||||
import type { Message } from 'discord.js';
|
import type { Message } from 'discord.js';
|
||||||
|
|
||||||
export class BotAppreciationListener extends Listener {
|
export class BotAppreciationListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'messageCreate',
|
event: 'messageCreate',
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ import type {
|
|||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
|
|
||||||
export class OldCommandDeniedListener extends Listener {
|
export class OldCommandDeniedListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'messageCommandDenied',
|
event: 'messageCommandDenied',
|
||||||
|
|||||||
@@ -21,11 +21,14 @@
|
|||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type { Message } from 'discord.js';
|
import type { Message } from 'discord.js';
|
||||||
import { getLastCount, addCount } from '#utils/database/counting';
|
import { getLastCount, addCount } from '#utils/database/fun/counting';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
|
||||||
export class XpListener extends Listener {
|
export class XpListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'messageCreate',
|
event: 'messageCreate',
|
||||||
@@ -41,6 +44,13 @@ export class XpListener extends Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!message.channel.isSendable()) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'Counting: The bot does not have permission to send messages in the counting chat!',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let lastCount = await getLastCount();
|
let lastCount = await getLastCount();
|
||||||
|
|
||||||
// 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
|
||||||
@@ -49,6 +59,7 @@ export class XpListener extends Listener {
|
|||||||
message.channel.send(
|
message.channel.send(
|
||||||
'An unexpected error occurred trying to set up the counting channel, please contact a developer!',
|
'An unexpected error occurred trying to set up the counting channel, please contact a developer!',
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +74,7 @@ export class XpListener extends Listener {
|
|||||||
message.channel.send(
|
message.channel.send(
|
||||||
'An unexpected error occurred, please contact a developer!',
|
'An unexpected error occurred, please contact a developer!',
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,10 @@ import {
|
|||||||
} from '#utils/database/dbExistingUser';
|
} 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.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'guildMemberRemove',
|
event: 'guildMemberRemove',
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ import type {
|
|||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
|
|
||||||
export class CommandDeniedListener extends Listener {
|
export class CommandDeniedListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'chatInputCommandDenied',
|
event: 'chatInputCommandDenied',
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ import { Listener } from '@sapphire/framework';
|
|||||||
import { setupTypes } from '#utils/database/outreach';
|
import { setupTypes } from '#utils/database/outreach';
|
||||||
|
|
||||||
export class EventTypesReadyListener extends Listener {
|
export class EventTypesReadyListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
once: true,
|
once: true,
|
||||||
|
|||||||
186
src/listeners/fixRoles.ts
Normal file
186
src/listeners/fixRoles.ts
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
/*
|
||||||
|
Animal Rights Advocates Discord Bot
|
||||||
|
Copyright (C) 2025 Anthony Berg
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
I used the Sapphire documentation and parts of the code from the Sapphire CLI to
|
||||||
|
create this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Listener } from '@sapphire/framework';
|
||||||
|
import { DurationFormatter } from '@sapphire/time-utilities';
|
||||||
|
import IDs from '#utils/ids';
|
||||||
|
import { fetchRoles } from '#utils/database/dbExistingUser';
|
||||||
|
import { checkActive } from '#utils/database/moderation/restriction';
|
||||||
|
import { getUser } from '#utils/database/fun/xp';
|
||||||
|
import { getGuild, getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import { isTextBasedChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
|
export class FixRolesOnReady extends Listener {
|
||||||
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
|
super(context, {
|
||||||
|
...options,
|
||||||
|
once: true,
|
||||||
|
event: 'ready',
|
||||||
|
// !!!!!!!!!!!! WARNING !!!!!!!!!!!!
|
||||||
|
// THIS SHOULD BE DISABLED BY DEFAULT
|
||||||
|
// THIS IS ONLY USED FOR RESTORING ROLES TO THE SERVER!
|
||||||
|
// ENABLING THIS UNINTENTIONALLY WILL CAUSE SLOWDOWNS TO THE BOT DUE TO RATE LIMITING!
|
||||||
|
enabled: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run() {
|
||||||
|
this.container.logger.info(
|
||||||
|
'FixRolesOnReady: Preparation before starting to fix the roles for each user...',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Fetching the Guild
|
||||||
|
const guild = await getGuild(IDs.guild);
|
||||||
|
|
||||||
|
if (guild === undefined) {
|
||||||
|
this.container.logger.error('FixRolesOnReady: Could not find the server');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetching the channel for the logs
|
||||||
|
// Leave the snowflake parameter empty for no logs
|
||||||
|
const logChannel = await getTextBasedChannel('');
|
||||||
|
const sendLogs = isTextBasedChannel(logChannel);
|
||||||
|
|
||||||
|
if (!sendLogs) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'FixRolesOnReady: Could not find the channel for bot logs.',
|
||||||
|
);
|
||||||
|
} else if (sendLogs && !logChannel.isSendable()) {
|
||||||
|
this.container.logger.info(
|
||||||
|
'FixRolesOnReady: No permission to send in bots logs channel.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all the current users
|
||||||
|
this.container.logger.info('FixRolesOnReady: Fetching all the members...');
|
||||||
|
if (sendLogs) {
|
||||||
|
logChannel.send('Fetching all the users in ARA!');
|
||||||
|
}
|
||||||
|
|
||||||
|
const members = await guild.members.fetch().catch(() => undefined);
|
||||||
|
|
||||||
|
if (members === undefined) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'FixRolesOnReady: Could not fetch all the members, this function is stopping now.',
|
||||||
|
);
|
||||||
|
if (sendLogs) {
|
||||||
|
logChannel.send("Never mind, something went wrong :'(");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalMembers = members.size;
|
||||||
|
|
||||||
|
this.container.logger.info(
|
||||||
|
`FixRolesOnReady: Done fetching ${totalMembers} members!`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Giving the roles to each user
|
||||||
|
let count = 0;
|
||||||
|
const startTime = new Date().getTime();
|
||||||
|
|
||||||
|
this.container.logger.info(
|
||||||
|
'FixRolesOnReady: Starting the process of fixing the roles for every member...',
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const [userId, member] of members) {
|
||||||
|
// Update the counter for the total number of users processed
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
// Send a message with an update for every 50 completions
|
||||||
|
// Checks if `channelLog` has been set to null
|
||||||
|
// The RHS of the modulo should be around 100
|
||||||
|
if (sendLogs && count % 250 === 0) {
|
||||||
|
const currentTime = new Date().getTime();
|
||||||
|
const runningTime = currentTime - startTime;
|
||||||
|
|
||||||
|
const remaining = totalMembers - count;
|
||||||
|
// Basing this on the fact that
|
||||||
|
const eta = remaining * (runningTime / count);
|
||||||
|
const estimate = new DurationFormatter().format(eta);
|
||||||
|
|
||||||
|
logChannel.send(
|
||||||
|
`Given roles to ${count} out of ${totalMembers} members. Estimated time until completion: ${estimate}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the user already has vegan or non-vegan role
|
||||||
|
|
||||||
|
// Checks if the user is restricted, and skips over them if they are
|
||||||
|
const restricted = await checkActive(userId);
|
||||||
|
|
||||||
|
if (
|
||||||
|
restricted ||
|
||||||
|
member.roles.cache.hasAny(...IDs.roles.restrictions.restricted)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the roles for the member in the database
|
||||||
|
const dbRoles = await fetchRoles(userId);
|
||||||
|
|
||||||
|
// Filters out the roles that the member does not have
|
||||||
|
const roles = dbRoles.filter((role) => !member.roles.cache.has(role));
|
||||||
|
|
||||||
|
if (!roles.includes(IDs.roles.nonvegan.nonvegan)) {
|
||||||
|
const xp = await getUser(userId);
|
||||||
|
|
||||||
|
if (xp !== null && xp.xp > 0) {
|
||||||
|
roles.push(IDs.roles.nonvegan.nonvegan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give the roles to the member
|
||||||
|
if (roles.length > 0) {
|
||||||
|
await member.roles.add(roles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log the completion
|
||||||
|
this.container.logger.info(
|
||||||
|
`FixRolesOnReady: Given roles to ${count}/${totalMembers}.`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add a delay so that there's around 4 users processed a second
|
||||||
|
await this.delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the logs that the fix has finished.
|
||||||
|
const endTime = new Date().getTime();
|
||||||
|
const totalTime = endTime - startTime;
|
||||||
|
const totalTimeWritten = new DurationFormatter().format(totalTime);
|
||||||
|
const finishMessage = `Finished fixing roles for all ${totalMembers} members! It took ${totalTimeWritten} to complete.`;
|
||||||
|
|
||||||
|
this.container.logger.info(`FixRolesOnReady: ${finishMessage}`);
|
||||||
|
if (sendLogs) {
|
||||||
|
logChannel.send(finishMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private delay(ms: number) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,15 +18,29 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import { ChannelType, EmbedBuilder } from 'discord.js';
|
import type { GuildChannel, EmbedBuilder } from 'discord.js';
|
||||||
import type { GuildChannel } from 'discord.js';
|
|
||||||
import { setTimeout } from 'timers/promises';
|
import { setTimeout } from 'timers/promises';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { checkActive, getRestrictions } from '#utils/database/restriction';
|
import {
|
||||||
import { findNotes } from '#utils/database/sus';
|
checkActive,
|
||||||
|
getRestrictions,
|
||||||
|
} from '#utils/database/moderation/restriction';
|
||||||
|
import { findNotes } from '#utils/database/moderation/sus';
|
||||||
|
import {
|
||||||
|
createRestrictLogEmbed,
|
||||||
|
createSusLogEmbed,
|
||||||
|
createWarningsEmbed,
|
||||||
|
} from '#utils/embeds';
|
||||||
|
import { fetchWarnings } from '#utils/database/moderation/warnings';
|
||||||
|
import { isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
import { getUser } from '#utils/fetcher';
|
||||||
|
import { isUser } from '#utils/typeChecking';
|
||||||
|
|
||||||
export class ModMailCreateListener extends Listener {
|
export class ModMailCreateListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'channelCreate',
|
event: 'channelCreate',
|
||||||
@@ -38,8 +52,7 @@ export class ModMailCreateListener extends Listener {
|
|||||||
if (channel.parentId !== IDs.categories.modMail) return;
|
if (channel.parentId !== IDs.categories.modMail) return;
|
||||||
|
|
||||||
// Checks if the channel is not a text channel
|
// Checks if the channel is not a text channel
|
||||||
if (!channel.isTextBased()) return;
|
if (!isTextChannel(channel)) return;
|
||||||
if (channel.type !== ChannelType.GuildText) return;
|
|
||||||
|
|
||||||
// Gets the guild
|
// Gets the guild
|
||||||
const { guild } = channel;
|
const { guild } = channel;
|
||||||
@@ -51,6 +64,13 @@ export class ModMailCreateListener extends Listener {
|
|||||||
// Get the user's ID
|
// Get the user's ID
|
||||||
const userId = topic[2];
|
const userId = topic[2];
|
||||||
|
|
||||||
|
// Gets user who created ModMail
|
||||||
|
const user = await getUser(userId);
|
||||||
|
|
||||||
|
if (!isUser(user)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
@@ -60,81 +80,21 @@ export class ModMailCreateListener extends Listener {
|
|||||||
|
|
||||||
// Creation of embeds
|
// Creation of embeds
|
||||||
// Restriction Logs
|
// Restriction Logs
|
||||||
const restrictEmbed = new EmbedBuilder()
|
const embeds: EmbedBuilder[] = [];
|
||||||
.setColor('#FF6700')
|
embeds.push(createRestrictLogEmbed(restrictions, user, guild));
|
||||||
.setTitle(`${restrictions.length} restrictions`)
|
|
||||||
.setFooter({ text: `ID: ${userId}` });
|
|
||||||
|
|
||||||
// Add up to 10 of the latest restrictions to the embed
|
// Warnings
|
||||||
for (
|
const warnings = await fetchWarnings(userId);
|
||||||
let i = restrictions.length > 10 ? restrictions.length - 10 : 0;
|
|
||||||
i < restrictions.length;
|
|
||||||
i += 1
|
|
||||||
) {
|
|
||||||
// Get mod names
|
|
||||||
let restMod = restrictions[i].modId;
|
|
||||||
const restModMember = guild.members.cache.get(restMod);
|
|
||||||
if (restModMember !== undefined) {
|
|
||||||
restMod = restModMember.displayName;
|
|
||||||
}
|
|
||||||
let endRestMod = restrictions[i].endModId;
|
|
||||||
if (endRestMod !== null) {
|
|
||||||
const endRestModMember = guild.members.cache.get(endRestMod);
|
|
||||||
if (endRestModMember !== undefined) {
|
|
||||||
endRestMod = endRestModMember.displayName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let restTitle = `Restriction: ${i + 1} | Restricted by: ${restMod} | `;
|
embeds.push(createWarningsEmbed(warnings, user, guild));
|
||||||
|
|
||||||
if (endRestMod !== null) {
|
|
||||||
restTitle += `Unrestricted by: ${endRestMod} | `;
|
|
||||||
} else {
|
|
||||||
restTitle += 'Currently Restricted | ';
|
|
||||||
}
|
|
||||||
|
|
||||||
restTitle += `Date: <t:${Math.floor(
|
|
||||||
restrictions[i].startTime.getTime() / 1000,
|
|
||||||
)}>`;
|
|
||||||
|
|
||||||
restrictEmbed.addFields({
|
|
||||||
name: restTitle,
|
|
||||||
value: restrictions[i].reason,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sus Notes
|
// Sus Notes
|
||||||
const notes = await findNotes(userId, true);
|
const notes = await findNotes(userId, true);
|
||||||
|
|
||||||
const susEmbed = new EmbedBuilder()
|
embeds.push(createSusLogEmbed(notes, user, guild));
|
||||||
.setColor('#0099ff')
|
|
||||||
.setTitle(`${notes.length} sus notes`);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
) {
|
|
||||||
// Get mod name
|
|
||||||
const modGuildMember = guild.members.cache.get(notes[i].modId);
|
|
||||||
let mod = notes[i].modId;
|
|
||||||
if (modGuildMember !== undefined) {
|
|
||||||
mod = modGuildMember.displayName;
|
|
||||||
}
|
|
||||||
// Add sus note to embed
|
|
||||||
susEmbed.addFields({
|
|
||||||
name: `Sus ID: ${
|
|
||||||
notes[i].id
|
|
||||||
} | Moderator: ${mod} | Date: <t:${Math.floor(
|
|
||||||
notes[i].time.getTime() / 1000,
|
|
||||||
)}>`,
|
|
||||||
value: notes[i].note,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a timeout for 1 second and then send the 2 embeds
|
// Set a timeout for 1 second and then send the 2 embeds
|
||||||
await setTimeout(1000);
|
await setTimeout(1000);
|
||||||
await channel.send({ embeds: [restrictEmbed, susEmbed] });
|
await channel.send({ embeds: embeds });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,15 @@
|
|||||||
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 { Client, TextChannel } from 'discord.js';
|
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import { isTextBasedChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class NonVeganAccessReady extends Listener {
|
export class NonVeganAccessReady extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
once: true,
|
once: true,
|
||||||
@@ -32,18 +36,12 @@ export class NonVeganAccessReady extends Listener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run(client: Client) {
|
public async run() {
|
||||||
let roles = client.channels.cache.get(IDs.channels.information.roles) as
|
const roles = await getTextBasedChannel(IDs.channels.information.roles);
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
if (!isTextBasedChannel(roles)) {
|
||||||
if (roles === undefined) {
|
this.container.logger.error('nonVeganAccess: Roles not found');
|
||||||
roles = (await client.channels.fetch(IDs.channels.information.roles)) as
|
return;
|
||||||
| TextChannel
|
|
||||||
| undefined;
|
|
||||||
if (roles === undefined) {
|
|
||||||
this.container.logger.error('nonVeganAccess: Roles not found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const botId = this.container.client.id;
|
const botId = this.container.client.id;
|
||||||
|
|||||||
@@ -22,9 +22,15 @@
|
|||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type { Client } from 'discord.js';
|
import type { Client } from 'discord.js';
|
||||||
|
import IDs from '#utils/ids';
|
||||||
|
import { getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import { isTextBasedChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class ReadyListener extends Listener {
|
export class ReadyListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
once: true,
|
once: true,
|
||||||
@@ -32,8 +38,24 @@ export class ReadyListener extends Listener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(client: Client) {
|
public async run(client: Client) {
|
||||||
const { username, id } = client.user!;
|
const { username, id } = client.user!;
|
||||||
this.container.logger.info(`Successfully logged in as ${username} (${id})`);
|
this.container.logger.info(`Successfully logged in as ${username} (${id})`);
|
||||||
|
|
||||||
|
const botLogChannel = await getTextBasedChannel(IDs.channels.logs.bot);
|
||||||
|
|
||||||
|
if (!isTextBasedChannel(botLogChannel)) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'ReadyListener: Could not find the channel for bot logs.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
} else if (!botLogChannel.isSendable()) {
|
||||||
|
this.container.logger.info(
|
||||||
|
'ReadyListener: No permission to send in bots logs channel.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
botLogChannel.send('The bot has started up!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,22 +18,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type {
|
import type { GuildMember, Snowflake, CategoryChannel } from 'discord.js';
|
||||||
GuildMember,
|
|
||||||
Snowflake,
|
|
||||||
CategoryChannel,
|
|
||||||
Guild,
|
|
||||||
TextChannel,
|
|
||||||
} from 'discord.js';
|
|
||||||
import { ChannelType } from 'discord.js';
|
|
||||||
import { fetchRoles, getLeaveRoles } from '#utils/database/dbExistingUser';
|
import { fetchRoles, getLeaveRoles } from '#utils/database/dbExistingUser';
|
||||||
import { blockTime } from '#utils/database/verification';
|
import { blockTime } from '#utils/database/verification';
|
||||||
import { checkActive, getSection } from '#utils/database/restriction';
|
import {
|
||||||
|
checkActive,
|
||||||
|
getSection,
|
||||||
|
} from '#utils/database/moderation/restriction';
|
||||||
import { blockedRoles, blockedRolesAfterRestricted } from '#utils/blockedRoles';
|
import { blockedRoles, blockedRolesAfterRestricted } from '#utils/blockedRoles';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getCategoryChannel, getVoiceChannel } from '#utils/fetcher';
|
||||||
|
import {
|
||||||
|
isCategoryChannel,
|
||||||
|
isTextChannel,
|
||||||
|
isVoiceChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class RolesJoinServerListener extends Listener {
|
export class RolesJoinServerListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'guildMemberAdd',
|
event: 'guildMemberAdd',
|
||||||
@@ -71,14 +76,11 @@ 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(
|
const restrictedCategory = await getCategoryChannel(
|
||||||
IDs.categories.restricted,
|
IDs.categories.restricted,
|
||||||
);
|
);
|
||||||
if (
|
if (isCategoryChannel(restrictedCategory)) {
|
||||||
restrictedCategory !== undefined &&
|
await this.restrictRun(member.id, restrictedCategory);
|
||||||
restrictedCategory.type === ChannelType.GuildCategory
|
|
||||||
) {
|
|
||||||
await this.restrictRun(member.id, restrictedCategory, member.guild);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,74 +99,77 @@ export class RolesJoinServerListener extends Listener {
|
|||||||
await member.roles.add(roles);
|
await member.roles.add(roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
const privateCategory = member.guild.channels.cache.get(
|
const privateCategory = await getCategoryChannel(IDs.categories.private);
|
||||||
IDs.categories.private,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
if (isCategoryChannel(privateCategory)) {
|
||||||
privateCategory !== undefined &&
|
await this.privateRun(member.id, privateCategory);
|
||||||
privateCategory.type === ChannelType.GuildCategory
|
|
||||||
) {
|
|
||||||
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(
|
private async restrictRun(userId: Snowflake, category: CategoryChannel) {
|
||||||
userId: Snowflake,
|
const textChannels = category.children.cache.filter((channel) =>
|
||||||
category: CategoryChannel,
|
isTextChannel(channel),
|
||||||
guild: Guild,
|
|
||||||
) {
|
|
||||||
const textChannels = category.children.cache.filter(
|
|
||||||
(c) => c.type === ChannelType.GuildText,
|
|
||||||
);
|
);
|
||||||
textChannels.forEach((c) => {
|
|
||||||
const textChannel = c as TextChannel;
|
for (const c of textChannels) {
|
||||||
|
const channel = c[1];
|
||||||
|
|
||||||
|
if (!isTextChannel(channel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Checks if the channel topic has the user's snowflake
|
// Checks if the channel topic has the user's snowflake
|
||||||
if (textChannel.topic?.includes(userId)) {
|
if (channel.topic !== null && channel.topic.includes(userId)) {
|
||||||
const topic = textChannel.topic.split(' ');
|
const topic = channel.topic.split(' ');
|
||||||
const vcId = topic[topic.indexOf(userId) + 1];
|
const vcId = topic[topic.indexOf(userId) + 1];
|
||||||
const voiceChannel = guild.channels.cache.get(vcId);
|
const voiceChannel = await getVoiceChannel(vcId);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
voiceChannel !== undefined &&
|
isVoiceChannel(voiceChannel) &&
|
||||||
voiceChannel.parentId === IDs.categories.restricted &&
|
voiceChannel.parentId === IDs.categories.restricted
|
||||||
voiceChannel.isVoiceBased()
|
|
||||||
) {
|
) {
|
||||||
voiceChannel.permissionOverwrites.edit(userId, { ViewChannel: true });
|
await voiceChannel.permissionOverwrites.edit(userId, {
|
||||||
|
ViewChannel: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
textChannel.permissionOverwrites.edit(userId, { ViewChannel: true });
|
|
||||||
|
await channel.permissionOverwrites.edit(userId, { ViewChannel: true });
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async privateRun(
|
private async privateRun(userId: Snowflake, category: CategoryChannel) {
|
||||||
userId: Snowflake,
|
const textChannels = category.children.cache.filter((channel) =>
|
||||||
category: CategoryChannel,
|
isTextChannel(channel),
|
||||||
guild: Guild,
|
|
||||||
) {
|
|
||||||
const textChannels = category.children.cache.filter(
|
|
||||||
(c) => c.type === ChannelType.GuildText,
|
|
||||||
);
|
);
|
||||||
textChannels.forEach((c) => {
|
|
||||||
const textChannel = c as TextChannel;
|
for (const c of textChannels) {
|
||||||
|
const channel = c[1];
|
||||||
|
|
||||||
|
if (!isTextChannel(channel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Checks if the channel topic has the user's snowflake
|
// Checks if the channel topic has the user's snowflake
|
||||||
if (textChannel.topic?.includes(userId)) {
|
if (channel.topic !== null && channel.topic.includes(userId)) {
|
||||||
const topic = textChannel.topic.split(' ');
|
const topic = channel.topic.split(' ');
|
||||||
const vcId = topic[topic.indexOf(userId) + 2];
|
const vcId = topic[topic.indexOf(userId) + 2];
|
||||||
const voiceChannel = guild.channels.cache.get(vcId);
|
const voiceChannel = await getVoiceChannel(vcId);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
voiceChannel !== undefined &&
|
isVoiceChannel(voiceChannel) &&
|
||||||
voiceChannel.parentId === IDs.categories.private &&
|
voiceChannel.parentId === IDs.categories.private
|
||||||
voiceChannel.isVoiceBased()
|
|
||||||
) {
|
) {
|
||||||
voiceChannel.permissionOverwrites.edit(userId, { ViewChannel: true });
|
await voiceChannel.permissionOverwrites.edit(userId, {
|
||||||
|
ViewChannel: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
textChannel.permissionOverwrites.edit(userId, { ViewChannel: true });
|
|
||||||
|
await channel.permissionOverwrites.edit(userId, { ViewChannel: true });
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private blockedRole(role: Snowflake) {
|
private blockedRole(role: Snowflake) {
|
||||||
|
|||||||
@@ -21,9 +21,14 @@ import { Listener } from '@sapphire/framework';
|
|||||||
import { EmbedBuilder } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
import type { Message } from 'discord.js';
|
import type { Message } from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getTextBasedChannel } from '#utils/fetcher';
|
||||||
|
import { isTextChannel } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class Suggestions extends Listener {
|
export class Suggestions extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'messageCreate',
|
event: 'messageCreate',
|
||||||
@@ -35,14 +40,19 @@ export class Suggestions extends Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mailbox = await this.container.client.channels.cache.get(
|
const mailbox = await getTextBasedChannel(IDs.channels.staff.mailbox);
|
||||||
IDs.channels.staff.mailbox,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (mailbox === undefined || !mailbox.isTextBased()) {
|
if (!isTextChannel(mailbox)) {
|
||||||
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;
|
||||||
|
} else if (!mailbox.isSendable()) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'Suggestions: The bot does not have permissions to send messages in the mailbox!',
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,14 @@
|
|||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type { VoiceState } from 'discord.js';
|
import type { VoiceState } from 'discord.js';
|
||||||
import { checkActive, removeMute } from '#utils/database/vcMute';
|
import { checkActive, removeMute } from '#utils/database/moderation/vcMute';
|
||||||
|
import { isGuildMember } from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class VCMuteListener extends Listener {
|
export class VCMuteListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'voiceStateUpdate',
|
event: 'voiceStateUpdate',
|
||||||
@@ -34,7 +38,7 @@ export class VCMuteListener extends Listener {
|
|||||||
if (oldState.channel === null && newState.channel !== null) {
|
if (oldState.channel === null && newState.channel !== null) {
|
||||||
const { member } = newState;
|
const { member } = newState;
|
||||||
|
|
||||||
if (member === null) {
|
if (!isGuildMember(member)) {
|
||||||
this.container.logger.error(
|
this.container.logger.error(
|
||||||
'VCMute Listener - GuildMember not found when joining',
|
'VCMute Listener - GuildMember not found when joining',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,10 +19,8 @@
|
|||||||
|
|
||||||
import { container, Listener } from '@sapphire/framework';
|
import { container, Listener } from '@sapphire/framework';
|
||||||
import type {
|
import type {
|
||||||
CategoryChannel,
|
|
||||||
ColorResolvable,
|
ColorResolvable,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
VoiceChannel,
|
|
||||||
VoiceState,
|
VoiceState,
|
||||||
GuildMember,
|
GuildMember,
|
||||||
Guild,
|
Guild,
|
||||||
@@ -30,7 +28,6 @@ import type {
|
|||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import {
|
import {
|
||||||
time,
|
time,
|
||||||
ChannelType,
|
|
||||||
PermissionsBitField,
|
PermissionsBitField,
|
||||||
ButtonBuilder,
|
ButtonBuilder,
|
||||||
ButtonInteraction,
|
ButtonInteraction,
|
||||||
@@ -50,13 +47,26 @@ import {
|
|||||||
startVerification,
|
startVerification,
|
||||||
finishVerification,
|
finishVerification,
|
||||||
} from '#utils/database/verification';
|
} from '#utils/database/verification';
|
||||||
import { findNotes } from '#utils/database/sus';
|
import { findNotes } from '#utils/database/moderation/sus';
|
||||||
import { addExistingUser } from '#utils/database/dbExistingUser';
|
import { addExistingUser } from '#utils/database/dbExistingUser';
|
||||||
import { rolesToString } from '#utils/formatter';
|
import { rolesToString } from '#utils/formatter';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import {
|
||||||
|
getCategoryChannel,
|
||||||
|
getGuildMember,
|
||||||
|
getVoiceChannel,
|
||||||
|
} from '#utils/fetcher';
|
||||||
|
import {
|
||||||
|
isCategoryChannel,
|
||||||
|
isGuildMember,
|
||||||
|
isVoiceChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class VerificationJoinVCListener extends Listener {
|
export class VerificationJoinVCListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'voiceStateUpdate',
|
event: 'voiceStateUpdate',
|
||||||
@@ -81,20 +91,19 @@ export class VerificationJoinVCListener extends Listener {
|
|||||||
const { client } = container;
|
const { client } = container;
|
||||||
const guild = client.guilds.cache.get(newState.guild.id);
|
const guild = client.guilds.cache.get(newState.guild.id);
|
||||||
|
|
||||||
if (channel === null || member === null || guild === undefined) {
|
if (member === null || guild === undefined) {
|
||||||
this.container.logger.error('Verification channel not found');
|
this.container.logger.error('Verification channel not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current category and channel
|
// Get current category and channel
|
||||||
const categoryGuild = guild.channels.cache.get(IDs.categories.verification);
|
const category = await getCategoryChannel(IDs.categories.verification);
|
||||||
const currentChannelGuild = guild.channels.cache.get(channel.id);
|
const currentChannel = await getVoiceChannel(channel.id);
|
||||||
if (currentChannelGuild === undefined || categoryGuild === undefined) {
|
|
||||||
|
if (!isCategoryChannel(category) || !isVoiceChannel(currentChannel)) {
|
||||||
this.container.logger.error('Verification channel not found');
|
this.container.logger.error('Verification channel not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const currentChannel = currentChannelGuild as VoiceChannel;
|
|
||||||
const category = categoryGuild as CategoryChannel;
|
|
||||||
|
|
||||||
const roles: Snowflake[] = [];
|
const roles: Snowflake[] = [];
|
||||||
|
|
||||||
@@ -151,19 +160,21 @@ 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(
|
await this.container.tasks.create(
|
||||||
'verifyTimeout',
|
|
||||||
{
|
{
|
||||||
channelId: channel.id,
|
name: 'verifyTimeout',
|
||||||
userId: member.id,
|
payload: {
|
||||||
|
channelId: channel.id,
|
||||||
|
userId: member.id,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
900_000,
|
900_000, // 15 minutes
|
||||||
); // 15 minutes
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check how many voice channels there are
|
// Check how many voice channels there are
|
||||||
const listVoiceChannels = category.children.cache.filter(
|
const listVoiceChannels = category.children.cache.filter((channel) =>
|
||||||
(c) => c.type === ChannelType.GuildVoice,
|
isVoiceChannel(channel),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create a text channel for verifiers only
|
// Create a text channel for verifiers only
|
||||||
@@ -295,11 +306,12 @@ export class VerificationJoinVCListener extends Listener {
|
|||||||
i += 1
|
i += 1
|
||||||
) {
|
) {
|
||||||
// Get mod name
|
// Get mod name
|
||||||
const modGuildMember = guild.members.cache.get(notes[i].modId);
|
const modGuildMember = await getGuildMember(notes[i].modId, guild);
|
||||||
let mod = notes[i].modId;
|
let mod = notes[i].modId;
|
||||||
if (modGuildMember !== undefined) {
|
if (isGuildMember(modGuildMember)) {
|
||||||
mod = modGuildMember.displayName;
|
mod = modGuildMember.displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add sus note to embed
|
// Add sus note to embed
|
||||||
embed.addFields({
|
embed.addFields({
|
||||||
name: `Sus ID: ${
|
name: `Sus ID: ${
|
||||||
@@ -490,10 +502,8 @@ 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(
|
const verifierGuildMember = await getGuildMember(button.user.id, guild);
|
||||||
button.user.id,
|
if (!isGuildMember(verifierGuildMember)) {
|
||||||
);
|
|
||||||
if (verifierGuildMember === undefined) {
|
|
||||||
await message.edit({ content: 'Verifier not found!' });
|
await message.edit({ content: 'Verifier not found!' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -506,11 +516,13 @@ export class VerificationJoinVCListener extends Listener {
|
|||||||
await giveVerificationRoles(user, info.roles);
|
await giveVerificationRoles(user, info.roles);
|
||||||
// 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) {
|
||||||
this.container.tasks.create(
|
await this.container.tasks.create(
|
||||||
'verifyUnblock',
|
|
||||||
{
|
{
|
||||||
userId: user.id,
|
name: 'verifyUnblock',
|
||||||
guildId: guild.id,
|
payload: {
|
||||||
|
userId: user.id,
|
||||||
|
guildId: guild.id,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
info.roles.vegan || info.roles.convinced ? 604800000 : 1814400000,
|
info.roles.vegan || info.roles.convinced ? 604800000 : 1814400000,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -18,13 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type {
|
import type { VoiceState } from 'discord.js';
|
||||||
VoiceState,
|
import { time } from 'discord.js';
|
||||||
CategoryChannel,
|
|
||||||
VoiceChannel,
|
|
||||||
TextChannel,
|
|
||||||
} 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 {
|
import {
|
||||||
@@ -35,9 +30,19 @@ import {
|
|||||||
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';
|
||||||
|
import {
|
||||||
|
isCategoryChannel,
|
||||||
|
isGuildMember,
|
||||||
|
isTextChannel,
|
||||||
|
isVoiceChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
import { getCategoryChannel, getGuildMember } from '#utils/fetcher';
|
||||||
|
|
||||||
export class VerificationLeaveVCListener extends Listener {
|
export class VerificationLeaveVCListener extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'voiceStateUpdate',
|
event: 'voiceStateUpdate',
|
||||||
@@ -60,59 +65,59 @@ export class VerificationLeaveVCListener extends Listener {
|
|||||||
const { channel } = oldState;
|
const { channel } = oldState;
|
||||||
const { guild } = newState;
|
const { guild } = newState;
|
||||||
|
|
||||||
if (channel === null || guild === undefined) {
|
if (!isVoiceChannel(channel) || guild === undefined) {
|
||||||
this.container.logger.error('Verification channel not found');
|
this.container.logger.error('Verification channel not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the category
|
// Get the category
|
||||||
const categoryGuild = guild.channels.cache.get(IDs.categories.verification);
|
const category = await getCategoryChannel(IDs.categories.verification);
|
||||||
if (categoryGuild === null) {
|
if (!isCategoryChannel(category)) {
|
||||||
this.container.logger.error('Verification channel not found');
|
this.container.logger.error('Verification channel not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const category = categoryGuild as CategoryChannel;
|
|
||||||
|
|
||||||
// Get the user that was being verified
|
// Get the user that was being verified
|
||||||
const userSnowflake = await getUser(channel.id);
|
const userSnowflake = await getUser(channel.id);
|
||||||
if (userSnowflake === null) {
|
if (userSnowflake === null) {
|
||||||
verifier = true;
|
verifier = true;
|
||||||
}
|
} else {
|
||||||
|
// Allow more people to join VC if there are less than 10 VCs
|
||||||
// Allow more people to join VC if there are less than 10 VCs
|
const member = await getGuildMember(userSnowflake, guild);
|
||||||
|
|
||||||
if (!verifier) {
|
|
||||||
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)) && isGuildMember(member)) {
|
||||||
// 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(member.id);
|
||||||
roles.push(IDs.roles.verifyBlock);
|
roles.push(IDs.roles.verifyBlock);
|
||||||
await user.roles
|
|
||||||
|
await member.roles
|
||||||
.add(roles)
|
.add(roles)
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
this.container.logger.error(
|
this.container.logger.error(
|
||||||
'Verification: User left but bot still tried to add roles',
|
'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 =
|
const incompleteCount =
|
||||||
(await countIncomplete(user.id)) % (leaveBan + 1);
|
(await countIncomplete(member.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(
|
await this.container.tasks.create(
|
||||||
'verifyUnblock',
|
|
||||||
{
|
{
|
||||||
userId: user.id,
|
name: 'verifyUnblock',
|
||||||
guildId: guild.id,
|
payload: {
|
||||||
|
userId: member.id,
|
||||||
|
guildId: guild.id,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
banLength,
|
banLength,
|
||||||
);
|
);
|
||||||
|
|
||||||
await user.user
|
await member.user
|
||||||
.send(
|
.send(
|
||||||
'You have been timed out as a verifier had not joined for 15 minutes or you disconnected from verification.\n\n' +
|
'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(
|
`You can verify again at: ${time(
|
||||||
@@ -124,8 +129,8 @@ export class VerificationLeaveVCListener extends Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check how many voice channels there are
|
// Check how many voice channels there are
|
||||||
const listVoiceChannels = category.children.cache.filter(
|
const listVoiceChannels = category.children.cache.filter((channel) =>
|
||||||
(c) => c.type === ChannelType.GuildVoice,
|
isVoiceChannel(channel),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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)
|
||||||
@@ -137,16 +142,22 @@ 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.filter(
|
const listTextChannels = category.children.cache.filter((channel) =>
|
||||||
(c) => c.type === ChannelType.GuildText,
|
isTextChannel(channel),
|
||||||
);
|
);
|
||||||
listTextChannels.forEach((c) => {
|
|
||||||
const textChannel = c as TextChannel;
|
for (const c of listTextChannels) {
|
||||||
// Checks if the channel topic has the user's snowflake
|
const channel = c[1];
|
||||||
if (textChannel.topic!.includes(userSnowflake!)) {
|
|
||||||
textChannel.delete();
|
if (!isTextChannel(channel)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// Checks if the channel topic has the user's snowflake
|
||||||
|
if (channel.topic !== null && channel.topic.includes(userSnowflake!)) {
|
||||||
|
await channel.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are no VCs left in verification after having the channel deleted
|
// If there are no VCs left in verification after having the channel deleted
|
||||||
@@ -160,9 +171,9 @@ export class VerificationLeaveVCListener extends Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const verification = listVoiceChannels.last() as VoiceChannel | undefined;
|
const verification = listVoiceChannels.last();
|
||||||
|
|
||||||
if (verification === undefined) {
|
if (!isVoiceChannel(verification)) {
|
||||||
this.container.logger.error(
|
this.container.logger.error(
|
||||||
'Verification: Verification channel not found.',
|
'Verification: Verification channel not found.',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ import type { Message } from 'discord.js';
|
|||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
|
||||||
export class VerificationMessageCounter extends Listener {
|
export class VerificationMessageCounter extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
event: 'messageCreate',
|
event: 'messageCreate',
|
||||||
|
|||||||
@@ -18,18 +18,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Listener } from '@sapphire/framework';
|
import { Listener } from '@sapphire/framework';
|
||||||
import type {
|
import type { VoiceChannel } from 'discord.js';
|
||||||
Client,
|
|
||||||
CategoryChannel,
|
|
||||||
TextChannel,
|
|
||||||
VoiceChannel,
|
|
||||||
} from 'discord.js';
|
|
||||||
import { ChannelType } from 'discord.js';
|
|
||||||
import { createVerificationVoice } from '#utils/verification';
|
import { createVerificationVoice } from '#utils/verification';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { getCategoryChannel } from '#utils/fetcher';
|
||||||
|
import {
|
||||||
|
isCategoryChannel,
|
||||||
|
isTextChannel,
|
||||||
|
isVoiceChannel,
|
||||||
|
} from '@sapphire/discord.js-utilities';
|
||||||
|
|
||||||
export class VerificationReady extends Listener {
|
export class VerificationReady extends Listener {
|
||||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
super(context, {
|
super(context, {
|
||||||
...options,
|
...options,
|
||||||
once: true,
|
once: true,
|
||||||
@@ -37,59 +40,67 @@ export class VerificationReady extends Listener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run(client: Client) {
|
public async run() {
|
||||||
// Get verification category
|
// Get verification category
|
||||||
let category = client.channels.cache.get(IDs.categories.verification) as
|
const category = await getCategoryChannel(IDs.categories.verification);
|
||||||
| CategoryChannel
|
|
||||||
| undefined;
|
if (!isCategoryChannel(category)) {
|
||||||
if (category === undefined) {
|
this.container.logger.error('verifyStart: Channel not found');
|
||||||
category = (await client.channels.fetch(IDs.categories.verification)) as
|
return;
|
||||||
| CategoryChannel
|
|
||||||
| undefined;
|
|
||||||
if (category === undefined) {
|
|
||||||
this.container.logger.error('verifyStart: Channel not found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check how many voice channels there are
|
// Check how many voice channels there are
|
||||||
const voiceChannels = category.children.cache.filter(
|
const voiceChannels = category.children.cache.filter((channel) =>
|
||||||
(c) => c.type === ChannelType.GuildVoice,
|
isVoiceChannel(channel),
|
||||||
);
|
);
|
||||||
const currentVCs: VoiceChannel[] = [];
|
const currentVCs: VoiceChannel[] = [];
|
||||||
const emptyVC: string[] = [];
|
const emptyVC: string[] = [];
|
||||||
|
|
||||||
// Delete voice channels
|
// Delete voice channels
|
||||||
voiceChannels.forEach((c) => {
|
for (const c of voiceChannels) {
|
||||||
const voiceChannel = c as VoiceChannel;
|
const channel = c[1];
|
||||||
if (voiceChannel.members.size === 0) {
|
|
||||||
emptyVC.push(voiceChannel.id);
|
if (!isVoiceChannel(channel)) {
|
||||||
voiceChannel.delete();
|
continue;
|
||||||
} else {
|
|
||||||
currentVCs.push(voiceChannel);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
if (channel.members.size === 0) {
|
||||||
|
emptyVC.push(channel.id);
|
||||||
|
await channel.delete();
|
||||||
|
} else {
|
||||||
|
currentVCs.push(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete text channels
|
// Delete text channels
|
||||||
const textChannels = category.children.cache.filter(
|
const textChannels = category.children.cache.filter((channel) =>
|
||||||
(c) => c.type === ChannelType.GuildText,
|
isTextChannel(channel),
|
||||||
);
|
);
|
||||||
textChannels.forEach((c) => {
|
|
||||||
const textChannel = c as TextChannel;
|
for (const c of textChannels) {
|
||||||
|
const channel = c[1];
|
||||||
|
|
||||||
|
if (!isTextChannel(channel)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Checks if the channel topic has the user's snowflake
|
// Checks if the channel topic has the user's snowflake
|
||||||
emptyVC.forEach((snowflake) => {
|
for (const snowflake in emptyVC) {
|
||||||
if (textChannel.topic!.includes(snowflake)) {
|
if (channel.topic !== null && channel.topic.includes(snowflake)) {
|
||||||
textChannel.delete();
|
await channel.delete();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
// Check if there is no voice channels, create verification
|
// Check if there is no voice channels, create verification
|
||||||
let verification = false;
|
let verification = false;
|
||||||
currentVCs.forEach((c) => {
|
|
||||||
if (c.name === 'Verification') {
|
currentVCs.forEach((channel) => {
|
||||||
|
if (channel.name === 'Verification') {
|
||||||
verification = true;
|
verification = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!verification) {
|
if (!verification) {
|
||||||
await createVerificationVoice(category);
|
await createVerificationVoice(category);
|
||||||
}
|
}
|
||||||
|
|||||||
90
src/listeners/verification/trusted.ts
Normal file
90
src/listeners/verification/trusted.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
/*
|
||||||
|
Animal Rights Advocates Discord Bot
|
||||||
|
Copyright (C) 2024 Anthony Berg
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Listener } from '@sapphire/framework';
|
||||||
|
import { GuildMember } from 'discord.js';
|
||||||
|
import IDs from '#utils/ids';
|
||||||
|
import { noModHistory, userPreviouslyHadRole } from '#utils/database/memberMod';
|
||||||
|
import { getRole } from '#utils/fetcher';
|
||||||
|
import { isRole } from '#utils/typeChecking';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives the trusted role to users who have levelled up to level 5
|
||||||
|
* and has not gotten any other warnings/restrictions prior.
|
||||||
|
*/
|
||||||
|
export class TrustedListener extends Listener {
|
||||||
|
public constructor(
|
||||||
|
context: Listener.LoaderContext,
|
||||||
|
options: Listener.Options,
|
||||||
|
) {
|
||||||
|
super(context, {
|
||||||
|
...options,
|
||||||
|
event: 'xpLevelUp',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(member: GuildMember, level: number) {
|
||||||
|
// Checks if the member has gotten level 7
|
||||||
|
// Has been nefred. Should take around 1.5 hours to get the trusted role now
|
||||||
|
if (level !== 7) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the user has been previously moderated
|
||||||
|
const noModerationHistory = await noModHistory(member.id);
|
||||||
|
if (!noModerationHistory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { guild } = member;
|
||||||
|
const trusted = await getRole(IDs.roles.trusted, guild);
|
||||||
|
|
||||||
|
if (!isRole(trusted)) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'TrustedXP Listener: the Trusted role could not be found in the guild.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the member has previously had the trusted role given/removed
|
||||||
|
const previouslyHadRole = await userPreviouslyHadRole(
|
||||||
|
member.id,
|
||||||
|
trusted.id,
|
||||||
|
);
|
||||||
|
if (previouslyHadRole) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the user already has the trusted role
|
||||||
|
if (member.roles.cache.has(trusted.id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gives the trusted role to the member
|
||||||
|
await member.roles.add(trusted);
|
||||||
|
|
||||||
|
// Send a DM to inform the member that they have been given the trusted role
|
||||||
|
await member.user.send(
|
||||||
|
`Hi, you have been given the ${trusted.name} as you have been interacting in ARA for a long enough time!` +
|
||||||
|
'\n\nThis role allows you to post attachments to the server and stream in VCs.' +
|
||||||
|
'\nMake sure that you follow the rules, especially by **not** posting anything **NSFW**, and **no animal products or consumption of animal products**.' +
|
||||||
|
`\n\nNot following these rules will result in the **immediate removal** of the ${trusted.name} role.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user