Merge pull request #444 from VermiumSifell/dev

Fix code smells
This commit is contained in:
Axel Olausson Holtenäs 2022-10-21 20:01:32 +02:00 committed by GitHub
commit eff85f1a85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
93 changed files with 1270 additions and 1019 deletions

View file

@ -6,7 +6,7 @@ DISCORD_CLIENT_ID=""
DISCORD_GUILD_ID=""
# Database
MONGO_URL="mongodb+srv://username:password@host/database?retryWrites=true&w=majority"
DATABASE_URL="file:./production.db"
# Encryption
ENCRYPTION_ALGORITHM="aes-256-ctr"

View file

@ -1,2 +0,0 @@
node_modules
dist

View file

@ -1,15 +0,0 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "no-loops", "prettier"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"rules": {
"no-console": 1,
"no-loops/no-loops": 2
}
}

8
.gitignore vendored
View file

@ -140,11 +140,3 @@ dist
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# Docker
database
docker-compose.local.yml
# Prisma
prisma/*.db*

View file

@ -1,14 +0,0 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ---------- | ------------------ |
| 2022.4.x | :white_check_mark: |
| < 2022.4.x | :x: |
## Reporting a Vulnerability
Report a security issue to Vermium#9649 on discord or vermium@zyner.org
I will try to fix the vulnerability within a month, often in some days only. If vulnerability is declined then still don't abuse it in any way you can.

2
prisma/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.db
*.db-journal

View file

@ -0,0 +1,16 @@
-- CreateTable
CREATE TABLE "GuildShopRoles" (
"guildId" TEXT NOT NULL,
"channelId" TEXT NOT NULL,
"roleId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"pricePerHour" INTEGER NOT NULL DEFAULT 5,
"lastPayed" DATETIME NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildShopRoles_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "GuildShopRoles_guildId_channelId_key" ON "GuildShopRoles"("guildId", "channelId");

View file

@ -0,0 +1,25 @@
/*
Warnings:
- You are about to drop the column `channelId` on the `GuildShopRoles` table. All the data in the column will be lost.
*/
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_GuildShopRoles" (
"guildId" TEXT NOT NULL,
"roleId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"pricePerHour" INTEGER NOT NULL DEFAULT 5,
"lastPayed" DATETIME NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildShopRoles_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildShopRoles" ("createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId") SELECT "createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId" FROM "GuildShopRoles";
DROP TABLE "GuildShopRoles";
ALTER TABLE "new_GuildShopRoles" RENAME TO "GuildShopRoles";
CREATE UNIQUE INDEX "GuildShopRoles_guildId_userId_roleId_key" ON "GuildShopRoles"("guildId", "userId", "roleId");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View file

@ -0,0 +1,20 @@
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_GuildShopRoles" (
"guildId" TEXT NOT NULL,
"roleId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"pricePerHour" INTEGER NOT NULL DEFAULT 5,
"lastPayed" DATETIME NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildShopRoles_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_guildId_userId_fkey" FOREIGN KEY ("guildId", "userId") REFERENCES "GuildMember" ("guildId", "userId") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildShopRoles" ("createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId") SELECT "createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId" FROM "GuildShopRoles";
DROP TABLE "GuildShopRoles";
ALTER TABLE "new_GuildShopRoles" RENAME TO "GuildShopRoles";
CREATE UNIQUE INDEX "GuildShopRoles_guildId_userId_roleId_key" ON "GuildShopRoles"("guildId", "userId", "roleId");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View file

@ -0,0 +1,20 @@
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_GuildShopRoles" (
"guildId" TEXT NOT NULL,
"roleId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"pricePerHour" INTEGER NOT NULL DEFAULT 5,
"lastPayed" DATETIME NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildShopRoles_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_guildId_fkey" FOREIGN KEY ("userId", "guildId") REFERENCES "GuildMember" ("userId", "guildId") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildShopRoles" ("createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId") SELECT "createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId" FROM "GuildShopRoles";
DROP TABLE "GuildShopRoles";
ALTER TABLE "new_GuildShopRoles" RENAME TO "GuildShopRoles";
CREATE UNIQUE INDEX "GuildShopRoles_guildId_userId_roleId_key" ON "GuildShopRoles"("guildId", "userId", "roleId");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View file

@ -0,0 +1,130 @@
/*
Warnings:
- You are about to alter the column `count` on the `GuildCounter` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `creditsEarned` on the `GuildMember` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `pointsEarned` on the `GuildMember` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `pricePerHour` on the `GuildShopRoles` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `cooldown` on the `Cooldown` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `creditsMinimumLength` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `creditsRate` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `creditsTimeout` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `creditsWorkRate` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `creditsWorkTimeout` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `pointsMinimumLength` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `pointsRate` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `pointsTimeout` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `shopRolesPricePerHour` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
- You are about to alter the column `reputationsEarned` on the `User` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
*/
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_GuildCounter" (
"guildId" TEXT NOT NULL,
"channelId" TEXT NOT NULL,
"triggerWord" TEXT NOT NULL,
"count" BIGINT NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildCounter_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildCounter" ("channelId", "count", "createdAt", "guildId", "triggerWord", "updatedAt") SELECT "channelId", "count", "createdAt", "guildId", "triggerWord", "updatedAt" FROM "GuildCounter";
DROP TABLE "GuildCounter";
ALTER TABLE "new_GuildCounter" RENAME TO "GuildCounter";
CREATE UNIQUE INDEX "GuildCounter_guildId_channelId_key" ON "GuildCounter"("guildId", "channelId");
CREATE TABLE "new_GuildMember" (
"userId" TEXT NOT NULL,
"guildId" TEXT NOT NULL,
"creditsEarned" BIGINT NOT NULL DEFAULT 0,
"pointsEarned" BIGINT NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildMember_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildMember" ("createdAt", "creditsEarned", "guildId", "pointsEarned", "updatedAt", "userId") SELECT "createdAt", "creditsEarned", "guildId", "pointsEarned", "updatedAt", "userId" FROM "GuildMember";
DROP TABLE "GuildMember";
ALTER TABLE "new_GuildMember" RENAME TO "GuildMember";
CREATE UNIQUE INDEX "GuildMember_userId_guildId_key" ON "GuildMember"("userId", "guildId");
CREATE TABLE "new_GuildShopRoles" (
"guildId" TEXT NOT NULL,
"roleId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"pricePerHour" BIGINT NOT NULL DEFAULT 5,
"lastPayed" DATETIME NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildShopRoles_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_guildId_fkey" FOREIGN KEY ("userId", "guildId") REFERENCES "GuildMember" ("userId", "guildId") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildShopRoles" ("createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId") SELECT "createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId" FROM "GuildShopRoles";
DROP TABLE "GuildShopRoles";
ALTER TABLE "new_GuildShopRoles" RENAME TO "GuildShopRoles";
CREATE UNIQUE INDEX "GuildShopRoles_guildId_userId_roleId_key" ON "GuildShopRoles"("guildId", "userId", "roleId");
CREATE TABLE "new_Cooldown" (
"guildId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"cooldown" BIGINT NOT NULL,
"timeoutId" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Cooldown_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Cooldown_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_Cooldown" ("cooldown", "createdAt", "guildId", "timeoutId", "updatedAt", "userId") SELECT "cooldown", "createdAt", "guildId", "timeoutId", "updatedAt", "userId" FROM "Cooldown";
DROP TABLE "Cooldown";
ALTER TABLE "new_Cooldown" RENAME TO "Cooldown";
CREATE UNIQUE INDEX "Cooldown_guildId_userId_timeoutId_key" ON "Cooldown"("guildId", "userId", "timeoutId");
CREATE TABLE "new_Guild" (
"id" TEXT NOT NULL,
"embedColorSuccess" TEXT NOT NULL DEFAULT '#22bb33',
"embedColorWait" TEXT NOT NULL DEFAULT '#f0ad4e',
"embedColorError" TEXT NOT NULL DEFAULT '#bb2124',
"embedFooterText" TEXT NOT NULL DEFAULT 'https://github.com/ZynerOrg/xyter',
"embedFooterIcon" TEXT NOT NULL DEFAULT 'https://github.com/ZynerOrg.png',
"creditsEnabled" BOOLEAN NOT NULL DEFAULT false,
"creditsRate" BIGINT NOT NULL DEFAULT 1,
"creditsTimeout" BIGINT NOT NULL DEFAULT 5,
"creditsWorkRate" BIGINT NOT NULL DEFAULT 25,
"creditsWorkTimeout" BIGINT NOT NULL DEFAULT 86400,
"creditsMinimumLength" BIGINT NOT NULL DEFAULT 5,
"pointsEnabled" BOOLEAN NOT NULL DEFAULT false,
"pointsRate" BIGINT NOT NULL DEFAULT 1,
"pointsTimeout" BIGINT NOT NULL DEFAULT 5,
"pointsMinimumLength" BIGINT NOT NULL DEFAULT 5,
"reputationsEnabled" BOOLEAN NOT NULL DEFAULT false,
"countersEnabled" BOOLEAN NOT NULL DEFAULT false,
"apiCpggUrlIv" TEXT,
"apiCpggUrlContent" TEXT,
"apiCpggTokenIv" TEXT,
"apiCpggTokenContent" TEXT,
"auditsEnabled" BOOLEAN NOT NULL DEFAULT false,
"auditsChannelId" TEXT,
"shopRolesEnabled" BOOLEAN NOT NULL DEFAULT false,
"shopRolesPricePerHour" BIGINT NOT NULL DEFAULT 5,
"welcomeEnabled" BOOLEAN NOT NULL DEFAULT false,
"welcomeJoinChannelId" TEXT,
"welcomeJoinChannelMessage" TEXT,
"welcomeLeaveChannelId" TEXT,
"welcomeLeaveChannelMessage" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_Guild" ("apiCpggTokenContent", "apiCpggTokenIv", "apiCpggUrlContent", "apiCpggUrlIv", "auditsChannelId", "auditsEnabled", "countersEnabled", "createdAt", "creditsEnabled", "creditsMinimumLength", "creditsRate", "creditsTimeout", "creditsWorkRate", "creditsWorkTimeout", "embedColorError", "embedColorSuccess", "embedColorWait", "embedFooterIcon", "embedFooterText", "id", "pointsEnabled", "pointsMinimumLength", "pointsRate", "pointsTimeout", "reputationsEnabled", "shopRolesEnabled", "shopRolesPricePerHour", "updatedAt", "welcomeEnabled", "welcomeJoinChannelId", "welcomeJoinChannelMessage", "welcomeLeaveChannelId", "welcomeLeaveChannelMessage") SELECT "apiCpggTokenContent", "apiCpggTokenIv", "apiCpggUrlContent", "apiCpggUrlIv", "auditsChannelId", "auditsEnabled", "countersEnabled", "createdAt", "creditsEnabled", "creditsMinimumLength", "creditsRate", "creditsTimeout", "creditsWorkRate", "creditsWorkTimeout", "embedColorError", "embedColorSuccess", "embedColorWait", "embedFooterIcon", "embedFooterText", "id", "pointsEnabled", "pointsMinimumLength", "pointsRate", "pointsTimeout", "reputationsEnabled", "shopRolesEnabled", "shopRolesPricePerHour", "updatedAt", "welcomeEnabled", "welcomeJoinChannelId", "welcomeJoinChannelMessage", "welcomeLeaveChannelId", "welcomeLeaveChannelMessage" FROM "Guild";
DROP TABLE "Guild";
ALTER TABLE "new_Guild" RENAME TO "Guild";
CREATE UNIQUE INDEX "Guild_id_key" ON "Guild"("id");
CREATE TABLE "new_User" (
"id" TEXT NOT NULL,
"reputationsEarned" BIGINT NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_User" ("createdAt", "id", "reputationsEarned", "updatedAt") SELECT "createdAt", "id", "reputationsEarned", "updatedAt" FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";
CREATE UNIQUE INDEX "User_id_key" ON "User"("id");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View file

@ -0,0 +1,130 @@
/*
Warnings:
- You are about to alter the column `reputationsEarned` on the `User` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `count` on the `GuildCounter` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `creditsEarned` on the `GuildMember` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `pointsEarned` on the `GuildMember` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `pricePerHour` on the `GuildShopRoles` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `creditsMinimumLength` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `creditsRate` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `creditsTimeout` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `creditsWorkRate` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `creditsWorkTimeout` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `pointsMinimumLength` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `pointsRate` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `pointsTimeout` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `shopRolesPricePerHour` on the `Guild` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
- You are about to alter the column `cooldown` on the `Cooldown` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Int`.
*/
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_User" (
"id" TEXT NOT NULL,
"reputationsEarned" INTEGER NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_User" ("createdAt", "id", "reputationsEarned", "updatedAt") SELECT "createdAt", "id", "reputationsEarned", "updatedAt" FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";
CREATE UNIQUE INDEX "User_id_key" ON "User"("id");
CREATE TABLE "new_GuildCounter" (
"guildId" TEXT NOT NULL,
"channelId" TEXT NOT NULL,
"triggerWord" TEXT NOT NULL,
"count" INTEGER NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildCounter_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildCounter" ("channelId", "count", "createdAt", "guildId", "triggerWord", "updatedAt") SELECT "channelId", "count", "createdAt", "guildId", "triggerWord", "updatedAt" FROM "GuildCounter";
DROP TABLE "GuildCounter";
ALTER TABLE "new_GuildCounter" RENAME TO "GuildCounter";
CREATE UNIQUE INDEX "GuildCounter_guildId_channelId_key" ON "GuildCounter"("guildId", "channelId");
CREATE TABLE "new_GuildMember" (
"userId" TEXT NOT NULL,
"guildId" TEXT NOT NULL,
"creditsEarned" INTEGER NOT NULL DEFAULT 0,
"pointsEarned" INTEGER NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildMember_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildMember" ("createdAt", "creditsEarned", "guildId", "pointsEarned", "updatedAt", "userId") SELECT "createdAt", "creditsEarned", "guildId", "pointsEarned", "updatedAt", "userId" FROM "GuildMember";
DROP TABLE "GuildMember";
ALTER TABLE "new_GuildMember" RENAME TO "GuildMember";
CREATE UNIQUE INDEX "GuildMember_userId_guildId_key" ON "GuildMember"("userId", "guildId");
CREATE TABLE "new_GuildShopRoles" (
"guildId" TEXT NOT NULL,
"roleId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"pricePerHour" INTEGER NOT NULL DEFAULT 5,
"lastPayed" DATETIME NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "GuildShopRoles_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "GuildShopRoles_userId_guildId_fkey" FOREIGN KEY ("userId", "guildId") REFERENCES "GuildMember" ("userId", "guildId") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_GuildShopRoles" ("createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId") SELECT "createdAt", "guildId", "lastPayed", "pricePerHour", "roleId", "updatedAt", "userId" FROM "GuildShopRoles";
DROP TABLE "GuildShopRoles";
ALTER TABLE "new_GuildShopRoles" RENAME TO "GuildShopRoles";
CREATE UNIQUE INDEX "GuildShopRoles_guildId_userId_roleId_key" ON "GuildShopRoles"("guildId", "userId", "roleId");
CREATE TABLE "new_Guild" (
"id" TEXT NOT NULL,
"embedColorSuccess" TEXT NOT NULL DEFAULT '#22bb33',
"embedColorWait" TEXT NOT NULL DEFAULT '#f0ad4e',
"embedColorError" TEXT NOT NULL DEFAULT '#bb2124',
"embedFooterText" TEXT NOT NULL DEFAULT 'https://github.com/ZynerOrg/xyter',
"embedFooterIcon" TEXT NOT NULL DEFAULT 'https://github.com/ZynerOrg.png',
"creditsEnabled" BOOLEAN NOT NULL DEFAULT false,
"creditsRate" INTEGER NOT NULL DEFAULT 1,
"creditsTimeout" INTEGER NOT NULL DEFAULT 5,
"creditsWorkRate" INTEGER NOT NULL DEFAULT 25,
"creditsWorkTimeout" INTEGER NOT NULL DEFAULT 86400,
"creditsMinimumLength" INTEGER NOT NULL DEFAULT 5,
"pointsEnabled" BOOLEAN NOT NULL DEFAULT false,
"pointsRate" INTEGER NOT NULL DEFAULT 1,
"pointsTimeout" INTEGER NOT NULL DEFAULT 5,
"pointsMinimumLength" INTEGER NOT NULL DEFAULT 5,
"reputationsEnabled" BOOLEAN NOT NULL DEFAULT false,
"countersEnabled" BOOLEAN NOT NULL DEFAULT false,
"apiCpggUrlIv" TEXT,
"apiCpggUrlContent" TEXT,
"apiCpggTokenIv" TEXT,
"apiCpggTokenContent" TEXT,
"auditsEnabled" BOOLEAN NOT NULL DEFAULT false,
"auditsChannelId" TEXT,
"shopRolesEnabled" BOOLEAN NOT NULL DEFAULT false,
"shopRolesPricePerHour" INTEGER NOT NULL DEFAULT 5,
"welcomeEnabled" BOOLEAN NOT NULL DEFAULT false,
"welcomeJoinChannelId" TEXT,
"welcomeJoinChannelMessage" TEXT,
"welcomeLeaveChannelId" TEXT,
"welcomeLeaveChannelMessage" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_Guild" ("apiCpggTokenContent", "apiCpggTokenIv", "apiCpggUrlContent", "apiCpggUrlIv", "auditsChannelId", "auditsEnabled", "countersEnabled", "createdAt", "creditsEnabled", "creditsMinimumLength", "creditsRate", "creditsTimeout", "creditsWorkRate", "creditsWorkTimeout", "embedColorError", "embedColorSuccess", "embedColorWait", "embedFooterIcon", "embedFooterText", "id", "pointsEnabled", "pointsMinimumLength", "pointsRate", "pointsTimeout", "reputationsEnabled", "shopRolesEnabled", "shopRolesPricePerHour", "updatedAt", "welcomeEnabled", "welcomeJoinChannelId", "welcomeJoinChannelMessage", "welcomeLeaveChannelId", "welcomeLeaveChannelMessage") SELECT "apiCpggTokenContent", "apiCpggTokenIv", "apiCpggUrlContent", "apiCpggUrlIv", "auditsChannelId", "auditsEnabled", "countersEnabled", "createdAt", "creditsEnabled", "creditsMinimumLength", "creditsRate", "creditsTimeout", "creditsWorkRate", "creditsWorkTimeout", "embedColorError", "embedColorSuccess", "embedColorWait", "embedFooterIcon", "embedFooterText", "id", "pointsEnabled", "pointsMinimumLength", "pointsRate", "pointsTimeout", "reputationsEnabled", "shopRolesEnabled", "shopRolesPricePerHour", "updatedAt", "welcomeEnabled", "welcomeJoinChannelId", "welcomeJoinChannelMessage", "welcomeLeaveChannelId", "welcomeLeaveChannelMessage" FROM "Guild";
DROP TABLE "Guild";
ALTER TABLE "new_Guild" RENAME TO "Guild";
CREATE UNIQUE INDEX "Guild_id_key" ON "Guild"("id");
CREATE TABLE "new_Cooldown" (
"guildId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"cooldown" INTEGER NOT NULL,
"timeoutId" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Cooldown_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Cooldown_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_Cooldown" ("cooldown", "createdAt", "guildId", "timeoutId", "updatedAt", "userId") SELECT "cooldown", "createdAt", "guildId", "timeoutId", "updatedAt", "userId" FROM "Cooldown";
DROP TABLE "Cooldown";
ALTER TABLE "new_Cooldown" RENAME TO "Cooldown";
CREATE UNIQUE INDEX "Cooldown_guildId_userId_timeoutId_key" ON "Cooldown"("guildId", "userId", "timeoutId");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View file

@ -1,3 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "sqlite"
provider = "sqlite"

View file

@ -58,8 +58,9 @@ model Guild {
welcomeLeaveChannelId String?
welcomeLeaveChannelMessage String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
GuildShopRoles GuildShopRoles[]
}
model User {
@ -72,8 +73,9 @@ model User {
reputationsEarned Int @default(0)
Cooldown Cooldown[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
GuildShopRoles GuildShopRoles[]
}
model GuildMember {
@ -89,8 +91,9 @@ model GuildMember {
creditsEarned Int @default(0)
pointsEarned Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
GuildShopRoles GuildShopRoles[]
// Unique Identifier
@@unique([userId, guildId])
@ -122,3 +125,20 @@ model Cooldown {
@@unique([guildId, userId, timeoutId])
}
model GuildShopRoles {
guildId String
roleId String
userId String
pricePerHour Int @default(5)
lastPayed DateTime
guild Guild @relation(fields: [guildId], references: [id])
user User @relation(fields: [userId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
member GuildMember? @relation(fields: [userId, guildId], references: [userId, guildId])
@@unique([guildId, userId, roleId])
}

View file

@ -1,43 +1,52 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import modules from "./modules";
// Modules
import moduleAudits from "./modules/audits";
import moduleCpgg from "./modules/cpgg";
import moduleCredits from "./modules/credits";
import moduleEmbeds from "./modules/embeds";
import modulePoints from "./modules/points";
import moduleShop from "./modules/shop";
import moduleWelcome from "./modules/welcome";
export const builder = new SlashCommandBuilder()
.setName("config")
.setDescription("Manage guild configurations.")
.setDMPermission(false)
.addSubcommand(modules.cpgg.builder)
.addSubcommand(modules.credits.builder)
.addSubcommand(modules.points.builder)
.addSubcommand(modules.welcome.builder)
.addSubcommand(modules.audits.builder)
.addSubcommand(modules.shop.builder)
.addSubcommand(modules.embeds.builder);
export const moduleData = modules;
// Modules
.addSubcommand(moduleAudits.builder)
.addSubcommand(moduleCpgg.builder)
.addSubcommand(moduleCredits.builder)
.addSubcommand(moduleEmbeds.builder)
.addSubcommand(modulePoints.builder)
.addSubcommand(moduleShop.builder)
.addSubcommand(moduleWelcome.builder);
// Execute function
export const execute = async (interaction: ChatInputCommandInteraction) => {
switch (interaction.options?.getSubcommand()) {
switch (interaction.options.getSubcommand()) {
case "audits":
await moduleAudits.execute(interaction);
break;
case "cpgg":
await modules.cpgg.execute(interaction);
await moduleCpgg.execute(interaction);
break;
case "credits":
await modules.credits.execute(interaction);
break;
case "points":
await modules.points.execute(interaction);
break;
case "welcome":
await modules.welcome.execute(interaction);
break;
case "audits":
await modules.audits.execute(interaction);
break;
case "shop":
await modules.shop.execute(interaction);
await moduleCredits.execute(interaction);
break;
case "embeds":
await modules.embeds.execute(interaction);
await moduleEmbeds.execute(interaction);
break;
case "points":
await modulePoints.execute(interaction);
break;
case "shop":
await moduleShop.execute(interaction);
break;
case "welcome":
await moduleWelcome.execute(interaction);
break;
default:
throw new Error("No module found for that specific command.");

View file

@ -1,21 +1,17 @@
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10";
import {
ChatInputCommandInteraction,
EmbedBuilder,
PermissionsBitField,
SlashCommandSubcommandBuilder,
} from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import checkPermission from "../../../../helpers/checkPermission";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("audits")
@ -35,6 +31,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { guild, options } = interaction;
const { successColor, footerText, footerIcon } = await getEmbedConfig(
guild

View file

@ -5,17 +5,13 @@ import {
PermissionsBitField,
} from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import checkPermission from "../../../../helpers/checkPermission";
import encryption from "../../../../helpers/encryption";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("cpgg")
@ -44,6 +40,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -5,84 +5,97 @@ import {
PermissionsBitField,
} from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import checkPermission from "../../../../helpers/checkPermission";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("credits")
.setDescription(`Credits`)
.setDescription(`Configure this guild's credits module.`)
.addBooleanOption((option) =>
option
.setName("status")
.setDescription("Should credits be enabled?")
.setName("enabled")
.setDescription("Do you want to activate the credit module?")
.setRequired(true)
)
.addNumberOption((option) =>
option
.setName("rate")
.setDescription("Amount of credits per message.")
.setDescription("Credit rate per message.")
.setRequired(true)
.setMinValue(1)
)
.addNumberOption((option) =>
option
.setName("minimum-length")
.setDescription("Minimum length of message to earn credits.")
.setDescription("Minimum message length to receive credit.")
.setRequired(true)
)
.addNumberOption((option) =>
option
.setName("work-rate")
.setDescription("Maximum amount of credits on work.")
.setDescription(
"The maximum amount of credit that can be obtained within a working day."
)
.setRequired(true)
.setMinValue(1)
)
.addNumberOption((option) =>
option
.setName("work-timeout")
.setDescription("Timeout between work schedules (seconds).")
.setDescription(
"How long you need to wait before you can work again provided in seconds."
)
.setRequired(true)
)
.addNumberOption((option) =>
option
.setName("timeout")
.setDescription("Timeout between earning credits (seconds).")
.setDescription(
"How long you need to wait before you can earn more credits."
)
.setRequired(true)
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);
const { guild, options } = interaction;
const status = options?.getBoolean("status");
const rate = options?.getNumber("rate");
const timeout = options?.getNumber("timeout");
const minimumLength = options?.getNumber("minimum-length");
const workRate = options?.getNumber("work-rate");
const workTimeout = options?.getNumber("work-timeout");
const enabled = options.getBoolean("enabled");
const rate = options.getNumber("rate");
const timeout = options.getNumber("timeout");
const minimumLength = options.getNumber("minimum-length");
const workRate = options.getNumber("work-rate");
const workTimeout = options.getNumber("work-timeout");
if (!guild) throw new Error("Guild is not found");
if (status === null) throw new Error("Status is null");
if (!rate) throw new Error("Rate is null");
if (!workRate) throw new Error("WorkRate is null");
if (!workTimeout) throw new Error("WorkTimeout is null");
if (!timeout) throw new Error("Timeout is null");
if (!minimumLength) throw new Error("Minimum Length is null");
if (!guild) throw new Error("Guild not found.");
if (typeof enabled !== "boolean")
throw new Error("Enabled option is not a boolean.");
if (typeof rate !== "number") throw new Error("Rate is not a number.");
if (typeof workRate !== "number")
throw new Error("Work rate is not a number.");
if (typeof workTimeout !== "number")
throw new Error("Work timeout is not a number.");
if (typeof timeout !== "number")
throw new Error("Timeout is not a number.");
if (typeof minimumLength !== "number")
throw new Error("Minimum length is not a number.");
const createGuild = await prisma.guild.upsert({
where: {
id: guild.id,
},
update: {
creditsEnabled: status,
creditsEnabled: enabled,
creditsRate: rate,
creditsTimeout: timeout,
creditsWorkRate: workRate,
@ -91,7 +104,7 @@ export default {
},
create: {
id: guild.id,
creditsEnabled: status,
creditsEnabled: enabled,
creditsRate: rate,
creditsTimeout: timeout,
creditsWorkRate: workRate,
@ -108,7 +121,7 @@ export default {
.setColor(successColor)
.addFields(
{
name: "🤖 Status",
name: "🤖 Enabled?",
value: `${createGuild.creditsEnabled}`,
inline: true,
},
@ -144,7 +157,7 @@ export default {
text: footerText,
});
await interaction?.editReply({
await interaction.editReply({
embeds: [interactionEmbed],
});
return;

View file

@ -5,15 +5,11 @@ import {
} from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import deferReply from "../../../../handlers/deferReply";
import checkPermission from "../../../../helpers/checkPermission";
import getValues from "./components/getValues";
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("embeds")
@ -50,6 +46,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { guild } = interaction;
if (!guild) throw new Error("Guild not found");

View file

@ -1,9 +0,0 @@
import audits from "./audits";
import cpgg from "./cpgg";
import credits from "./credits";
import embeds from "./embeds";
import points from "./points";
import shop from "./shop";
import welcome from "./welcome";
export default { audits, credits, points, cpgg, shop, welcome, embeds };

View file

@ -5,16 +5,12 @@ import {
PermissionsBitField,
} from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import checkPermission from "../../../../helpers/checkPermission";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("points")
@ -45,6 +41,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -5,16 +5,12 @@ import {
PermissionsBitField,
} from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import checkPermission from "../../../../helpers/checkPermission";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("shop")
@ -33,6 +29,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -6,16 +6,12 @@ import {
PermissionsBitField,
} from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import checkPermission from "../../../../helpers/checkPermission";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("welcome")
@ -56,6 +52,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -1,18 +1,24 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import modules from "./modules";
// Modules
import moduleView from "./modules/view";
export const builder = new SlashCommandBuilder()
.setName("counters")
.setDescription("View guild counters")
.setDMPermission(false)
.addSubcommand(modules.view.builder);
export const moduleData = modules;
// Modules
.addSubcommand(moduleView.builder);
// Execute function
export const execute = async (interaction: ChatInputCommandInteraction) => {
if (interaction.options.getSubcommand() === "view") {
await modules.view.execute(interaction);
switch (interaction.options.getSubcommand()) {
case "view":
await moduleView.execute(interaction);
break;
default:
throw new Error("No module found for that command.");
}
};

View file

@ -1,3 +0,0 @@
import view from "./view";
export default { view };

View file

@ -2,11 +2,10 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10";
import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
export default {
metadata: { guildOnly: true, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("view")
@ -23,6 +22,8 @@ export default {
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, false);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -2,34 +2,39 @@ import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import logger from "../../middlewares/logger";
import modules from "./modules";
// Modules
import moduleBalance from "./modules/balance";
import moduleGift from "./modules/gift";
import moduleTop from "./modules/top";
import moduleWork from "./modules/work";
export const builder = new SlashCommandBuilder()
.setName("credits")
.setDescription("Manage your credits.")
.setDMPermission(false)
.addSubcommand(modules.balance.builder)
.addSubcommand(modules.gift.builder)
.addSubcommand(modules.top.builder)
.addSubcommand(modules.work.builder);
export const moduleData = modules;
// Modules
.addSubcommand(moduleBalance.builder)
.addSubcommand(moduleGift.builder)
.addSubcommand(moduleTop.builder)
.addSubcommand(moduleWork.builder);
// Execute function
export const execute = async (interaction: ChatInputCommandInteraction) => {
const { options } = interaction;
switch (options.getSubcommand()) {
case "balance":
await modules.balance.execute(interaction);
await moduleBalance.execute(interaction);
break;
case "gift":
await modules.gift.execute(interaction);
await moduleGift.execute(interaction);
break;
case "top":
await modules.top.execute(interaction);
await moduleTop.execute(interaction);
break;
case "work":
await modules.work.execute(interaction);
await moduleWork.execute(interaction);
break;
default:
logger.silly(`Unknown subcommand ${options.getSubcommand()}`);

View file

@ -1,11 +1,11 @@
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { CommandInteraction, EmbedBuilder } from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("balance")
@ -17,6 +17,8 @@ export default {
);
},
execute: async (interaction: CommandInteraction) => {
await deferReply(interaction, true);
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { options, user, guild } = interaction;

View file

@ -7,13 +7,12 @@ import {
} from "discord.js";
import transferCredits from "../../../../helpers/transferCredits";
// Configurations
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
// Handlers
// Function
export default {
metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("gift")
@ -35,6 +34,8 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -1,6 +0,0 @@
import balance from "./balance";
import gift from "./gift";
import top from "./top";
import work from "./work";
export default { balance, gift, top, work };

View file

@ -2,6 +2,7 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { GuildMember } from "@prisma/client";
import { CommandInteraction, EmbedBuilder } from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
@ -12,6 +13,8 @@ export default {
return command.setName("top").setDescription(`View the top users`);
},
execute: async (interaction: CommandInteraction) => {
await deferReply(interaction, false);
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { guild } = interaction;

View file

@ -3,21 +3,22 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import Chance from "chance";
import { CommandInteraction, EmbedBuilder } from "discord.js";
// Models
import * as cooldown from "../../../../handlers/cooldown";
import { command as CooldownCommand } from "../../../../handlers/cooldown";
// Configurations
import getEmbedConfig from "../../../../helpers/getEmbedData";
// Helpers
// Handlers
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import logger from "../../../../middlewares/logger";
export default {
metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command.setName("work").setDescription(`Work to earn credits`);
},
execute: async (interaction: CommandInteraction) => {
await deferReply(interaction, true);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
); // Destructure member
@ -50,7 +51,7 @@ export default {
logger.silly(createGuild);
await cooldown.command(interaction, createGuild.creditsWorkTimeout);
await CooldownCommand(interaction, createGuild.creditsWorkTimeout);
const creditsEarned = chance.integer({
min: 0,

View file

@ -1,20 +1,21 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import modules from "./modules";
export const moduleData = modules;
// Modules
import moduleLookup from "./modules/lookup";
export const builder = new SlashCommandBuilder()
.setName("dns")
.setDescription("DNS commands.")
.addSubcommand(modules.lookup.builder);
// Modules
.addSubcommand(moduleLookup.builder);
// Execute the command
export const execute = async (interaction: ChatInputCommandInteraction) => {
switch (interaction.options.getSubcommand()) {
case "lookup":
await modules.lookup.execute(interaction);
await moduleLookup.execute(interaction);
break;
default:
throw new Error(

View file

@ -1,3 +0,0 @@
import lookup from "./lookup";
export default { lookup };

View file

@ -1,11 +1,10 @@
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import axios from "axios";
import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
export default {
metadata: { guildOnly: false, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("lookup")
@ -20,6 +19,8 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, false);
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const embedTitle = "[:hammer:] Utility (Lookup)";

View file

@ -2,21 +2,21 @@ import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import logger from "../../middlewares/logger";
import modules from "./modules";
// Modules
import moduleMeme from "./modules/meme";
export const builder = new SlashCommandBuilder()
.setName("fun")
.setDescription("Fun commands.")
.addSubcommand(modules.meme.builder);
export const moduleData = modules;
.addSubcommand(moduleMeme.builder);
// Execute function
export const execute = async (interaction: ChatInputCommandInteraction) => {
const { options } = interaction;
if (options.getSubcommand() === "meme") {
await modules.meme.execute(interaction);
await moduleMeme.execute(interaction);
} else {
logger.silly(`Unknown subcommand ${options.getSubcommand()}`);
}

View file

@ -1,5 +0,0 @@
import meme from "./meme";
export default {
meme,
};

View file

@ -1,16 +1,20 @@
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import axios from "axios";
import { CommandInteraction, EmbedBuilder } from "discord.js";
import { command as CooldownCommand } from "../../../../handlers/cooldown";
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
export default {
metadata: { guildOnly: false, ephemeral: false, cooldown: 15 },
builder: (command: SlashCommandSubcommandBuilder) => {
return command.setName("meme").setDescription("Get a meme from r/memes)");
},
execute: async (interaction: CommandInteraction) => {
await deferReply(interaction, false);
await CooldownCommand(interaction, 15);
const { guild } = interaction;
const embedConfig = await getEmbedConfig(guild);

View file

@ -2,17 +2,19 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
// Groups
import modules from "./modules";
export const moduleData = modules;
// Modules
import moduleCounters from "./modules/counters";
import moduleCredits from "./modules/credits";
// Function
export const builder = new SlashCommandBuilder()
.setName("manage")
.setDescription("Manage the bot.")
.addSubcommandGroup(modules.counters.builder)
.addSubcommandGroup(modules.credits.builder);
.setDMPermission(false)
// Modules
.addSubcommandGroup(moduleCounters.builder)
.addSubcommandGroup(moduleCredits.builder);
export const execute = async (interaction: ChatInputCommandInteraction) => {
// Destructure
@ -20,11 +22,11 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
switch (options.getSubcommandGroup()) {
case "credits": {
await modules.credits.execute(interaction);
await moduleCredits.execute(interaction);
break;
}
case "counters": {
await modules.counters.execute(interaction);
await moduleCounters.execute(interaction);
break;
}
default: {

View file

@ -3,35 +3,32 @@ import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
// Modules
import modules from "./modules";
import moduleAdd from "./modules/add";
import moduleRemove from "./modules/remove";
// Function
export const moduleData = modules;
export default {
builder: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("counters")
.setDescription("Manage guild counters.")
.addSubcommand(moduleAdd.builder)
.addSubcommand(moduleRemove.builder);
},
execute: async (interaction: ChatInputCommandInteraction) => {
const { options } = interaction;
// Create a discord builder
export const builder = (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("counters")
.setDescription("Manage guild counters.")
.addSubcommand(modules.add.builder)
.addSubcommand(modules.remove.builder);
};
// Execute the command
export const execute = async (interaction: ChatInputCommandInteraction) => {
const { options } = interaction;
switch (options.getSubcommand()) {
case "add": {
await modules.add.execute(interaction);
break;
}
case "remove": {
await modules.remove.execute(interaction);
break;
}
default: {
throw new Error("Could not found a module for that command.");
}
}
switch (options.getSubcommand()) {
case "add": {
await moduleAdd.execute(interaction);
break;
}
case "remove": {
await moduleRemove.execute(interaction);
break;
}
default: {
throw new Error("Could not found a module for that command.");
}
}
},
};

View file

@ -6,6 +6,8 @@ import {
EmbedBuilder,
PermissionsBitField,
} from "discord.js";
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
// Configurations
import prisma from "../../../../../../handlers/database";
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
@ -13,12 +15,6 @@ import logger from "../../../../../../middlewares/logger";
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("add")
@ -43,6 +39,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -1,4 +0,0 @@
import add from "./add";
import remove from "./remove";
export default { add, remove };

View file

@ -7,18 +7,14 @@ import {
EmbedBuilder,
PermissionsBitField,
} from "discord.js";
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
// Configurations
import prisma from "../../../../../../handlers/database";
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("remove")
@ -32,6 +28,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -1,38 +1,43 @@
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import modules from "./modules";
export const moduleData = modules;
// Modules
import moduleGive from "./modules/give";
import moduleGiveaway from "./modules/giveaway";
import moduleSet from "./modules/set";
import moduleTake from "./modules/take";
import moduleTransfer from "./modules/transfer";
export const builder = (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("credits")
.setDescription("Manage the credits of a user.")
.addSubcommand(modules.give.builder)
.addSubcommand(modules.set.builder)
.addSubcommand(modules.take.builder)
.addSubcommand(modules.transfer.builder)
.addSubcommand(modules.giveaway.builder);
};
export const execute = async (interaction: ChatInputCommandInteraction) => {
switch (interaction.options.getSubcommand()) {
case "give":
await modules.give.execute(interaction);
break;
case "set":
await modules.set.execute(interaction);
break;
case "take":
await modules.take.execute(interaction);
break;
case "transfer":
await modules.transfer.execute(interaction);
break;
case "giveaway":
await modules.giveaway.execute(interaction);
break;
default:
throw new Error("No module found for that specific command");
}
export default {
builder: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("credits")
.setDescription("Manage the credits of a user.")
.addSubcommand(moduleGive.builder)
.addSubcommand(moduleSet.builder)
.addSubcommand(moduleTake.builder)
.addSubcommand(moduleTransfer.builder)
.addSubcommand(moduleGiveaway.builder);
},
execute: async (interaction: ChatInputCommandInteraction) => {
switch (interaction.options.getSubcommand()) {
case "give":
await moduleGive.execute(interaction);
break;
case "set":
await moduleSet.execute(interaction);
break;
case "take":
await moduleTake.execute(interaction);
break;
case "transfer":
await moduleTransfer.execute(interaction);
break;
case "giveaway":
await moduleGiveaway.execute(interaction);
break;
default:
throw new Error("No module found for that specific command");
}
},
};

View file

@ -13,14 +13,10 @@ import pluralize from "../../../../../../helpers/pluralize";
// Models
// Handlers
import prisma from "../../../../../../handlers/database";
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("give")
@ -39,6 +35,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
); // Destructure

View file

@ -13,17 +13,13 @@ import { v4 as uuidv4 } from "uuid";
import encryption from "../../../../../../helpers/encryption";
// Configurations
import prisma from "../../../../../../handlers/database";
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
import logger from "../../../../../../middlewares/logger";
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("giveaway")
@ -49,6 +45,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
); // Destructure

View file

@ -1,7 +0,0 @@
import give from "./give";
import giveaway from "./giveaway";
import set from "./set";
import take from "./take";
import transfer from "./transfer";
export default { give, set, take, transfer, giveaway };

View file

@ -11,16 +11,12 @@ import {
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
// Handlers
import prisma from "../../../../../../handlers/database";
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
import logger from "../../../../../../middlewares/logger";
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("set")
@ -39,6 +35,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { options, guild } = interaction;

View file

@ -12,16 +12,12 @@ import getEmbedConfig from "../../../../../../helpers/getEmbedData";
import pluralize from "../../../../../../helpers/pluralize";
// Handlers
import prisma from "../../../../../../handlers/database";
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
import logger from "../../../../../../middlewares/logger";
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("take")
@ -40,6 +36,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild); // Destructure
const { guild, options } = interaction;

View file

@ -8,17 +8,12 @@ import {
} from "discord.js";
import transferCredits from "../../../../../../helpers/transferCredits";
// Configurations
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
// Handlers../../../../../../../helpers/userData
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [PermissionsBitField.Flags.ManageGuild],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("transfer")
@ -43,8 +38,13 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild); // Destructure member
await deferReply(interaction, true);
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
); // Destructure member
const { guild, options } = interaction;
// Get options

View file

@ -1,4 +0,0 @@
import * as counters from "./counters";
import * as credits from "./credits";
export default { counters, credits };

View file

@ -1,20 +1,21 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import modules from "./modules";
export const moduleData = modules;
// Modules
import modulePrune from "./modules/prune";
export const builder = new SlashCommandBuilder()
.setName("moderation")
.setDescription("Moderation.")
.setDMPermission(false)
.addSubcommand(modules.prune.builder);
.addSubcommand(modulePrune.builder);
// Execute the command
export const execute = async (interaction: ChatInputCommandInteraction) => {
switch (interaction.options.getSubcommand()) {
case "prune": {
await modules.prune.execute(interaction);
await modulePrune.execute(interaction);
break;
}
default: {

View file

@ -1,3 +0,0 @@
import prune from "./prune";
export default { prune };

View file

@ -6,17 +6,13 @@ import {
EmbedBuilder,
PermissionsBitField,
} from "discord.js";
import deferReply from "../../../../handlers/deferReply";
import checkPermission from "../../../../helpers/checkPermission";
// Configurations
import getEmbedConfig from "../../../../helpers/getEmbedData";
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: false,
permissions: [PermissionsBitField.Flags.ManageMessages],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("prune")
@ -32,6 +28,10 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, false);
checkPermission(interaction, PermissionsBitField.Flags.ManageMessages);
const { errorColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -3,26 +3,27 @@ import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
// Modules
import modules from "./modules";
// Handlers
export const moduleData = modules;
import moduleGive from "./modules/give";
import moduleView from "./modules/view";
// Function
export const builder = new SlashCommandBuilder()
.setName("reputation")
.setDescription("Manage reputation.")
.addSubcommand(modules.give.builder)
.addSubcommand(modules.view.builder);
.setDMPermission(false)
// Modules
.addSubcommand(moduleGive.builder)
.addSubcommand(moduleView.builder);
// Execute function
export const execute = async (interaction: ChatInputCommandInteraction) => {
if (interaction.options.getSubcommand() === "give") {
await modules.give.execute(interaction);
await moduleGive.execute(interaction);
return;
}
if (interaction.options.getSubcommand() === "view") {
await modules.view.execute(interaction);
await moduleView.execute(interaction);
return;
}
};

View file

@ -6,10 +6,9 @@ import logger from "../../../../middlewares/logger";
import noSelfReputation from "./components/noSelfReputation";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
export default {
metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("give")
@ -35,6 +34,8 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
const { options, user, guild } = interaction;
const { successColor, footerText, footerIcon } = await getEmbedConfig(

View file

@ -1,4 +0,0 @@
import give from "./give";
import view from "./view";
export default { give, view };

View file

@ -1,12 +1,11 @@
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("view")
@ -19,7 +18,9 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
const { options, user, guild } = interaction;
await deferReply(interaction, true);
const { options, guild } = interaction;
const { successColor, footerText, footerIcon } = await getEmbedConfig(
guild

View file

@ -3,18 +3,18 @@ import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
// Modules
import modules from "./modules";
// Handlers
export const moduleData = modules;
import moduleCpgg from "./modules/cpgg";
import moduleRoles from "./modules/roles";
// Function
export const builder = new SlashCommandBuilder()
.setName("shop")
.setDescription("Shop for credits and custom roles.")
.addSubcommand(modules.cpgg.builder)
.addSubcommandGroup(modules.roles.builder);
.setDMPermission(false)
// Modules
.addSubcommand(moduleCpgg.builder)
.addSubcommandGroup(moduleRoles.builder);
// Execute the command
export const execute = async (interaction: ChatInputCommandInteraction) => {
@ -22,7 +22,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
switch (options.getSubcommand()) {
case "cpgg": {
await modules.cpgg.execute(interaction);
await moduleCpgg.execute(interaction);
break;
}
default: {
@ -32,7 +32,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
switch (options.getSubcommandGroup()) {
case "roles": {
await modules.roles.execute(interaction);
await moduleRoles.execute(interaction);
break;
}
default: {

View file

@ -10,13 +10,12 @@ import {
} from "discord.js";
import { v4 as uuidv4 } from "uuid";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import encryption from "../../../../helpers/encryption";
import getEmbedData from "../../../../helpers/getEmbedData";
import logger from "../../../../middlewares/logger";
export default {
metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("cpgg")
@ -29,6 +28,8 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
await deferReply(interaction, true);
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedData(interaction.guild);
const { options, guild, user, client } = interaction;

View file

@ -1,4 +0,0 @@
import cpgg from "./cpgg";
import * as roles from "./roles";
export default { cpgg, roles };

View file

@ -5,39 +5,41 @@ import { ChatInputCommandInteraction } from "discord.js";
// Handlers
// Modules
import modules from "./modules";
import moduleBuy from "./modules/buy";
import moduleCancel from "./modules/cancel";
import guildSchema from "../../../../models/guild";
import prisma from "../../../../handlers/database";
export const moduleData = modules;
export default {
builder: (group: SlashCommandSubcommandGroupBuilder) => {
return (
group
.setName("roles")
.setDescription("Shop for custom roles.")
// Function
export const builder = (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("roles")
.setDescription("Shop for custom roles.")
.addSubcommand(modules.buy.builder)
.addSubcommand(modules.cancel.builder);
};
export const execute = async (interaction: ChatInputCommandInteraction) => {
if (!interaction.guild) return;
const { options, guild } = interaction;
const guildDB = await guildSchema?.findOne({
guildId: guild?.id,
});
if (guildDB === null) return;
if (!guildDB.shop.roles.status)
throw new Error("This server has disabled shop roles.");
if (options?.getSubcommand() === "buy") {
await modules.buy.execute(interaction);
}
if (options?.getSubcommand() === "cancel") {
await modules.cancel.execute(interaction);
}
// Modules
.addSubcommand(moduleBuy.builder)
.addSubcommand(moduleCancel.builder)
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
if (!interaction.guild) return;
const { options, guild } = interaction;
const getGuild = await prisma.guild.findUnique({
where: { id: guild.id },
});
if (!getGuild) throw new Error("Guild not found");
if (!getGuild.shopRolesEnabled)
throw new Error("This server has disabled shop roles.");
if (options?.getSubcommand() === "buy") {
await moduleBuy.execute(interaction);
}
if (options?.getSubcommand() === "cancel") {
await moduleCancel.execute(interaction);
}
},
};

View file

@ -1,15 +1,24 @@
// Dependencies
// Helpers
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import {
ChatInputCommandInteraction,
ColorResolvable,
EmbedBuilder,
GuildMemberRoleManager,
} from "discord.js";
import deferReply from "../../../../../../handlers/deferReply";
import getEmbedData from "../../../../../../helpers/getEmbedData";
import logger from "../../../../../../middlewares/logger";
// Configurations
// import fetchUser from "../../../../../../helpers/userData";
// Models
import prisma from "../../../../../../handlers/database";
import pluralize from "../../../../../../helpers/pluralize";
// Function
export default {
metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("buy")
@ -28,65 +37,142 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
// const { successColor, footerText, footerIcon } = await getEmbedConfig(
// interaction.guild
// );
// const { options, guild, user, member } = interaction;
// const optionName = options?.getString("name");
// const optionColor = options?.getString("color");
// // If amount is null
// if (optionName === null)
// throw new Error("We could not read your requested name");
// await guild?.roles
// .create({
// name: optionName,
// color: optionColor as ColorResolvable,
// reason: `${user?.id} bought from shop`,
// })
// .then(async (role) => {
// // Get guild object
// const guildDB = await guildSchema?.findOne({
// guildId: guild?.id,
// });
// const userDB = await fetchUser(user, guild);
// if (userDB === null) {
// return logger?.silly(`User is null`);
// }
// if (guildDB === null) {
// return logger?.silly(`Guild is null`);
// }
// if (guildDB.shop === null) {
// return logger?.silly(`Shop is null`);
// }
// const { pricePerHour } = guildDB.shop.roles;
// userDB.credits -= pricePerHour;
// await userDB?.save();
// await shopRolesSchema?.create({
// roleId: role?.id,
// userId: user?.id,
// guildId: guild?.id,
// pricePerHour,
// lastPayed: new Date(),
// });
// await (member?.roles as GuildMemberRoleManager)?.add(role?.id);
// logger?.silly(`Role ${role?.name} was bought by ${user?.tag}`);
// const interactionEmbed = new EmbedBuilder()
// .setTitle("[:shopping_cart:] Buy")
// .setDescription(
// `You bought **${optionName}** for **${pluralize(
// pricePerHour,
// "credit"
// )}**.`
// )
// .setTimestamp()
// .setColor(successColor)
// .setFooter({ text: footerText, iconURL: footerIcon });
// return interaction?.editReply({
// embeds: [interactionEmbed],
// });
// })
// .catch(() => {
// throw new Error("Failed creating role.");
// });
await deferReply(interaction, true);
const { successColor, footerText, footerIcon } = await getEmbedData(
interaction.guild
);
const { options, guild, user, member } = interaction;
const optionName = options?.getString("name");
const optionColor = options?.getString("color");
// If amount is null
if (optionName === null)
throw new Error("We could not read your requested name");
await guild?.roles
.create({
name: optionName,
color: optionColor as ColorResolvable,
reason: `${user?.id} bought from shop`,
})
.then(async (role) => {
const userId = "SNOWFLKAE";
const guildId = "SNOWFLAKE";
const createGuildMember = await prisma.guildMember.upsert({
where: {
userId_guildId: {
userId,
guildId,
},
},
update: {},
create: {
user: {
connectOrCreate: {
create: {
id: userId,
},
where: {
id: userId,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guildId,
},
where: {
id: guildId,
},
},
},
},
include: {
user: true,
guild: true,
},
});
logger.silly(createGuildMember);
// Get guild object
const pricePerHour = createGuildMember.guild.shopRolesPricePerHour;
const updateGuildMember = await prisma.guildMember.update({
where: {
userId_guildId: {
userId,
guildId,
},
},
data: {
creditsEarned: { decrement: pricePerHour },
},
});
logger.silly(updateGuildMember);
const createShopRole = await prisma.guildShopRoles.upsert({
where: {
guildId_userId_roleId: {
guildId: guild.id,
userId: user.id,
roleId: role.id,
},
},
update: {},
create: {
roleId: role.id,
lastPayed: new Date(),
user: {
connectOrCreate: {
create: {
id: user.id,
},
where: {
id: user.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
},
include: {
user: true,
guild: true,
},
});
logger.silly(createShopRole);
await (member?.roles as GuildMemberRoleManager)?.add(role?.id);
logger?.silly(`Role ${role?.name} was bought by ${user?.tag}`);
const interactionEmbed = new EmbedBuilder()
.setTitle("[:shopping_cart:] Buy")
.setDescription(
`You bought **${optionName}** for **${pluralize(
pricePerHour,
"credit"
)}**.`
)
.setTimestamp()
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon });
return interaction?.editReply({
embeds: [interactionEmbed],
});
})
.catch(() => {
throw new Error("Failed creating role.");
});
},
};

View file

@ -1,15 +1,24 @@
// Dependencies
// Helpers
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import {
ChatInputCommandInteraction,
EmbedBuilder,
GuildMemberRoleManager,
} from "discord.js";
// Configurations
// import fetchUser from "../../../../../../helpers/userData";
// Models
import deferReply from "../../../../../../handlers/deferReply";
import logger from "../../../../../../middlewares/logger";
// Configurations
// Models
import prisma from "../../../../../../handlers/database";
import getEmbedData from "../../../../../../helpers/getEmbedData";
import pluralize from "../../../../../../helpers/pluralize";
// Function
export default {
metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("cancel")
@ -22,45 +31,97 @@ export default {
);
},
execute: async (interaction: ChatInputCommandInteraction) => {
// const { successColor, footerText, footerIcon } = await getEmbedConfig(
// interaction.guild
// );
// const { options, guild, user, member } = interaction;
// const optionRole = options.getRole("role");
// if (optionRole === null)
// throw new Error("We could not read your requested role.");
// const roleExist = await shopRolesSchema?.findOne({
// guildId: guild?.id,
// userId: user?.id,
// roleId: optionRole?.id,
// });
// if (roleExist === null) return;
// await (member?.roles as GuildMemberRoleManager)?.remove(optionRole?.id);
// await guild?.roles
// .delete(optionRole?.id, `${user?.id} canceled from shop`)
// .then(async () => {
// const userDB = await fetchUser(user, guild);
// if (userDB === null) {
// return logger?.silly(`User is null`);
// }
// await shopRolesSchema?.deleteOne({
// roleId: optionRole?.id,
// userId: user?.id,
// guildId: guild?.id,
// });
// const interactionEmbed = new EmbedBuilder()
// .setTitle("[:shopping_cart:] Cancel")
// .setDescription(`You have canceled ${optionRole.name}.`)
// .setTimestamp()
// .setColor(successColor)
// .addFields({
// name: "Your balance",
// value: `${pluralize(userDB?.credits, "credit")}`,
// })
// .setFooter({ text: footerText, iconURL: footerIcon });
// return interaction?.editReply({
// embeds: [interactionEmbed],
// });
// });
await deferReply(interaction, true);
const { successColor, footerText, footerIcon } = await getEmbedData(
interaction.guild
);
const { options, guild, user, member } = interaction;
const optionRole = options.getRole("role");
if (optionRole === null)
throw new Error("We could not read your requested role.");
if (!guild) throw new Error("No guild specified");
if (!user) throw new Error("No user specified");
const roleExist = await prisma.guildShopRoles.findUnique({
where: {
guildId_userId_roleId: {
guildId: guild.id,
userId: user.id,
roleId: optionRole.id,
},
},
});
if (roleExist === null) return;
await (member?.roles as GuildMemberRoleManager)?.remove(optionRole?.id);
await guild?.roles
.delete(optionRole?.id, `${user?.id} canceled from shop`)
.then(async () => {
const createGuildMember = await prisma.guildMember.upsert({
where: {
userId_guildId: {
userId: user.id,
guildId: guild.id,
},
},
update: {},
create: {
user: {
connectOrCreate: {
create: {
id: user.id,
},
where: {
id: user.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
},
include: {
user: true,
guild: true,
},
});
logger.silly(createGuildMember);
if (!createGuildMember) throw new Error("Guild member not created");
const deleteShopRole = await prisma.guildShopRoles.delete({
where: {
guildId_userId_roleId: {
guildId: guild?.id,
userId: user?.id,
roleId: optionRole?.id,
},
},
});
logger.silly(deleteShopRole);
const interactionEmbed = new EmbedBuilder()
.setTitle("[:shopping_cart:] Cancel")
.setDescription(`You have canceled ${optionRole.name}.`)
.setTimestamp()
.setColor(successColor)
.addFields({
name: "Your balance",
value: `${pluralize(createGuildMember.creditsEarned, "credit")}`,
})
.setFooter({ text: footerText, iconURL: footerIcon });
return interaction?.editReply({
embeds: [interactionEmbed],
});
});
},
};

View file

@ -1,7 +0,0 @@
import buy from "./buy";
import cancel from "./cancel";
export default {
buy,
cancel,
};

View file

@ -1,32 +1,36 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { ChatInputCommandInteraction } from "discord.js";
import modules from "./modules";
export const moduleData = modules;
// Modules
import moduleAbout from "./modules/about";
import moduleAvatar from "./modules/avatar";
import modulePing from "./modules/ping";
import moduleStats from "./modules/stats";
export const builder = new SlashCommandBuilder()
.setName("utility")
.setDescription("Common utility.")
.addSubcommand(modules.about.builder)
.addSubcommand(modules.stats.builder)
.addSubcommand(modules.avatar.builder)
.addSubcommand(modules.ping.builder);
// Modules
.addSubcommand(moduleAbout.builder)
.addSubcommand(moduleStats.builder)
.addSubcommand(moduleAvatar.builder)
.addSubcommand(modulePing.builder);
// Execute the command
export const execute = async (interaction: ChatInputCommandInteraction) => {
switch (interaction.options.getSubcommand()) {
case "about":
await modules.about.execute(interaction);
await moduleAbout.execute(interaction);
break;
case "stats":
await modules.stats.execute(interaction);
await moduleStats.execute(interaction);
break;
case "avatar":
await modules.avatar.execute(interaction);
await moduleAvatar.execute(interaction);
break;
case "ping":
await modules.ping.execute(interaction);
await modulePing.execute(interaction);
break;
default:
throw new Error(

View file

@ -7,17 +7,18 @@ import {
CommandInteraction,
EmbedBuilder,
} from "discord.js";
import deferReply from "../../../../handlers/deferReply";
// Configurations
import getEmbedConfig from "../../../../helpers/getEmbedData";
// Function
export default {
metadata: { guildOnly: false, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command.setName("about").setDescription("About this bot!)");
},
execute: async (interaction: CommandInteraction) => {
await deferReply(interaction, false);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -1,10 +1,9 @@
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { CommandInteraction, EmbedBuilder } from "discord.js";
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
export default {
metadata: { guildOnly: false, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("avatar")
@ -16,6 +15,8 @@ export default {
);
},
execute: async (interaction: CommandInteraction) => {
await deferReply(interaction, false);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -1,11 +0,0 @@
import about from "./about";
import avatar from "./avatar";
import ping from "./ping";
import stats from "./stats";
export default {
avatar,
about,
stats,
ping,
};

View file

@ -2,16 +2,17 @@
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { CommandInteraction, EmbedBuilder } from "discord.js";
// Configurations
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
// Function
export default {
metadata: { guildOnly: false, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command.setName("ping").setDescription("Ping this bot");
},
execute: async (interaction: CommandInteraction) => {
await deferReply(interaction, false);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -1,14 +1,15 @@
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { CommandInteraction, EmbedBuilder } from "discord.js";
import deferReply from "../../../../handlers/deferReply";
import getEmbedConfig from "../../../../helpers/getEmbedData";
export default {
metadata: { guildOnly: false, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command.setName("stats").setDescription("Check bot statistics!)");
},
execute: async (interaction: CommandInteraction) => {
await deferReply(interaction, false);
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);

View file

@ -1,25 +1,28 @@
import { ChannelType, EmbedBuilder, GuildMember } from "discord.js";
import prisma from "../../handlers/database";
import getEmbedConfig from "../../helpers/getEmbedData";
import logger from "../../middlewares/logger";
import guildSchema from "../../models/guild";
export default {
execute: async (member: GuildMember) => {
const { client, guild } = member;
const guildData = await guildSchema.findOne({ guildId: member.guild.id });
if (!guildData) {
throw new Error("Could not find guild");
}
if (guildData.audits.status !== true) return;
if (!guildData.audits.channelId) {
const getGuild = await prisma.guild.findUnique({
where: { id: member.guild.id },
});
if (!getGuild) throw new Error("Guild not found");
if (getGuild.auditsEnabled !== true) return;
if (!getGuild.auditsChannelId) {
throw new Error("Channel not found");
}
const embedConfig = await getEmbedConfig(guild);
const channel = client.channels.cache.get(guildData.audits.channelId);
if (channel?.type !== ChannelType.GuildText) {
const channel = client.channels.cache.get(getGuild.auditsChannelId);
if (!channel) throw new Error("Channel not found");
if (channel.type !== ChannelType.GuildText) {
throw new Error("Channel must be a text channel");
}

View file

@ -1,6 +1,6 @@
import { EmbedBuilder, GuildMember, TextChannel } from "discord.js";
import { ChannelType, EmbedBuilder, GuildMember } from "discord.js";
import prisma from "../../handlers/database";
import getEmbedConfig from "../../helpers/getEmbedData";
import guildSchema from "../../models/guild";
export default {
execute: async (member: GuildMember) => {
@ -8,29 +8,33 @@ export default {
member.guild
);
const guildData = await guildSchema.findOne({ guildId: member.guild.id });
const getGuild = await prisma.guild.findUnique({
where: { id: member.guild.id },
});
if (!getGuild) throw new Error("Guild not found");
const { client } = member;
if (guildData === null) return;
if (guildData.welcome.status !== true) return;
if (!guildData.welcome.joinChannel) return;
if (getGuild.welcomeEnabled !== true) return;
if (!getGuild.welcomeJoinChannelId) return;
const channel = client.channels.cache.get(
`${guildData.welcome.joinChannel}`
`${getGuild.welcomeJoinChannelId}`
);
if (channel === null) return;
if (!channel) throw new Error("Channel not found");
if (channel.type !== ChannelType.GuildText)
throw new Error("Channel is not a text channel");
(channel as TextChannel).send({
channel.send({
embeds: [
new EmbedBuilder()
.setColor(successColor)
.setTitle(`${member.user.username} has joined the server!`)
.setThumbnail(member.user.displayAvatarURL())
.setDescription(
guildData.welcome.joinChannelMessage ||
getGuild.welcomeJoinChannelMessage ||
"Configure a join message in the `/settings guild welcome`."
)
.setTimestamp()

View file

@ -1,24 +1,25 @@
import { ChannelType, EmbedBuilder, GuildMember } from "discord.js";
import prisma from "../../handlers/database";
import getEmbedConfig from "../../helpers/getEmbedData";
import logger from "../../middlewares/logger";
import guildSchema from "../../models/guild";
export default {
execute: async (member: GuildMember) => {
const { client, guild } = member;
const guildData = await guildSchema.findOne({ guildId: member.guild.id });
if (!guildData) {
throw new Error("Could not find guild");
}
if (guildData.audits.status !== true) return;
if (!guildData.audits.channelId) {
const getGuild = await prisma.guild.findUnique({
where: { id: member.guild.id },
});
if (!getGuild) throw new Error("Guild not found");
if (getGuild.auditsEnabled !== true) return;
if (!getGuild.auditsChannelId) {
throw new Error("Channel not found");
}
const embedConfig = await getEmbedConfig(guild);
const channel = client.channels.cache.get(guildData.audits.channelId);
const channel = client.channels.cache.get(getGuild.auditsChannelId);
if (channel?.type !== ChannelType.GuildText) {
throw new Error("Channel must be a text channel");
}

View file

@ -1,6 +1,6 @@
import { EmbedBuilder, GuildMember, TextChannel } from "discord.js";
import { ChannelType, EmbedBuilder, GuildMember } from "discord.js";
import prisma from "../../handlers/database";
import getEmbedConfig from "../../helpers/getEmbedData";
import guildSchema from "../../models/guild";
export default {
execute: async (member: GuildMember) => {
@ -8,29 +8,33 @@ export default {
member.guild
);
const guildData = await guildSchema.findOne({ guildId: member.guild.id });
const getGuild = await prisma.guild.findUnique({
where: { id: member.guild.id },
});
if (!getGuild) throw new Error("Guild not found");
const { client } = member;
if (guildData === null) return;
if (guildData.welcome.status !== true) return;
if (!guildData.welcome.leaveChannel) return;
if (getGuild.welcomeEnabled !== true) return;
if (!getGuild.welcomeLeaveChannelId) return;
const channel = client.channels.cache.get(
`${guildData.welcome.leaveChannel}`
`${getGuild.welcomeLeaveChannelId}`
);
if (channel === null) return;
if (!channel) throw new Error("Channel not found");
if (channel.type !== ChannelType.GuildText)
throw new Error("Channel is not a text channel");
(channel as TextChannel).send({
channel.send({
embeds: [
new EmbedBuilder()
.setColor(errorColor)
.setTitle(`${member.user.username} has left the server!`)
.setThumbnail(member.user.displayAvatarURL())
.setDescription(
guildData.welcome.leaveChannelMessage ||
getGuild.welcomeLeaveChannelMessage ||
"Configure a leave message in the `/settings guild welcome`."
)
.setTimestamp()

View file

@ -1,7 +1,7 @@
import { BaseInteraction, ChannelType, EmbedBuilder } from "discord.js";
import prisma from "../../handlers/database";
import getEmbedConfig from "../../helpers/getEmbedData";
import logger from "../../middlewares/logger";
import guildSchema from "../../models/guild";
export default {
execute: async (interaction: BaseInteraction) => {
@ -9,22 +9,21 @@ export default {
if (interaction.guild === null) return;
const getGuild = await prisma.guild.findUnique({
where: { id: interaction.guild.id },
});
if (!getGuild) throw new Error("Guild not found");
const { footerText, footerIcon, successColor } = await getEmbedConfig(
interaction.guild
);
const guildData = await guildSchema.findOne({
guildId: interaction.guild.id,
});
const { client } = interaction;
if (guildData === null) return;
if (getGuild.auditsEnabled !== true) return;
if (!getGuild.auditsChannelId) return;
if (guildData.audits.status !== true) return;
if (!guildData.audits.channelId) return;
const channel = client.channels.cache.get(`${guildData.audits.channelId}`);
const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`);
if (!channel) return;
if (channel.type !== ChannelType.GuildText) return;

View file

@ -1,8 +1,5 @@
// Dependencies
import { ChatInputCommandInteraction } from "discord.js";
import { command as CooldownCommand } from "../../../../handlers/cooldown";
import deferReply from "../../../../handlers/deferReply";
import getCommandMetadata from "../../../../helpers/getCommandMetadata";
export default async (interaction: ChatInputCommandInteraction) => {
if (!interaction.isCommand()) return;
@ -11,24 +8,24 @@ export default async (interaction: ChatInputCommandInteraction) => {
const currentCommand = client.commands.get(commandName);
if (!currentCommand) throw new Error(`Unknown command ${commandName}`);
const metadata = await getCommandMetadata(interaction, currentCommand);
await deferReply(interaction, metadata.ephemeral || false);
// const metadata = await getCommandMetadata(interaction, currentCommand);
// await deferReply(interaction, metadata.ephemeral || false);
if (metadata.guildOnly && !interaction.guild)
throw new Error("This command is guild only.");
// if (metadata.guildOnly && !interaction.guild)
// throw new Error("This command is guild only.");
if (
metadata.permissions &&
metadata.guildOnly &&
!interaction.memberPermissions?.has(metadata.permissions)
)
throw new Error("You don't have the required permissions");
// if (metadata.dmOnly && interaction.guild)
// throw new Error("This command is only available in DM");
if (metadata.dmOnly && interaction.guild)
throw new Error("This command is only available in DM");
// if (
// metadata.permissions &&
// metadata.guildOnly &&
// !interaction.memberPermissions?.has(metadata.permissions)
// )
// throw new Error("You don't have the required permissions");
if (metadata.cooldown) {
await CooldownCommand(interaction, metadata.cooldown);
}
// if (metadata.cooldown) {
// await CooldownCommand(interaction, metadata.cooldown);
// }
await currentCommand.execute(interaction);
};

View file

@ -7,6 +7,7 @@ import {
import { IEventOptions } from "../../interfaces/EventOptions";
import logger from "../../middlewares/logger";
// Dependencies
import audits from "./audits";
import { handleCommandInteraction as HandlersHandleCommandInteraction } from "./handlers";
export const options: IEventOptions = {
@ -21,7 +22,7 @@ export const execute = async (interaction: BaseInteraction) => {
`New interaction: ${id} in guild: ${guild?.name} (${guild?.id})`
);
// await audits.execute(interaction);
await audits.execute(interaction);
switch (interaction.type) {
case InteractionType.ApplicationCommand:

View file

@ -1,7 +1,7 @@
import { ChannelType, EmbedBuilder, Message } from "discord.js";
import prisma from "../../handlers/database";
import getEmbedConfig from "../../helpers/getEmbedData";
import logger from "../../middlewares/logger";
import guildSchema from "../../models/guild";
export default {
execute: async (message: Message) => {
@ -13,18 +13,19 @@ export default {
message.guild
);
const guildData = await guildSchema.findOne({
guildId: message.guild.id,
const getGuild = await prisma.guild.findUnique({
where: { id: message.guild.id },
});
if (!getGuild) throw new Error("Guild not found");
const { client } = message;
if (guildData === null) return;
if (!getGuild) throw new Error("Guild not found");
if (guildData.audits.status !== true) return;
if (!guildData.audits.channelId) return;
if (getGuild.auditsEnabled !== true) return;
if (!getGuild.auditsChannelId) return;
const channel = client.channels.cache.get(`${guildData.audits.channelId}`);
const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`);
if (!channel) return;
if (channel.type !== ChannelType.GuildText) return;

View file

@ -1,8 +1,8 @@
/* eslint-disable no-loops/no-loops */
import { ChannelType, EmbedBuilder, Message } from "discord.js";
import prisma from "../../handlers/database";
import getEmbedConfig from "../../helpers/getEmbedData";
import logger from "../../middlewares/logger";
import guildSchema from "../../models/guild";
export default {
execute: async (oldMessage: Message, newMessage: Message) => {
@ -16,18 +16,17 @@ export default {
newMessage.guild
);
const guildData = await guildSchema.findOne({
guildId: oldMessage.guild.id,
const getGuild = await prisma.guild.findUnique({
where: { id: oldMessage.guild.id },
});
if (!getGuild) throw new Error("Guild not found");
const { client } = oldMessage;
if (guildData === null) return;
if (getGuild.auditsEnabled !== true) return;
if (!getGuild.auditsChannelId) return;
if (guildData.audits.status !== true) return;
if (!guildData.audits.channelId) return;
const channel = client.channels.cache.get(`${guildData.audits.channelId}`);
const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`);
if (!channel) return;
if (channel.type !== ChannelType.GuildText) return;

View file

@ -21,10 +21,6 @@ export const register = async (client: Client) => {
throw new Error(
`📦 No command builder found while importing "${commandName}"`
);
if (!command.moduleData)
throw new Error(
`📦 No command moduleData found while importing "${commandName}"`
);
// Add command to collection
client.commands.set(command.builder.name, command);

View file

@ -0,0 +1,3 @@
import { PrismaClient } from '@prisma/client'
export default new PrismaClient()

View file

@ -0,0 +1,12 @@
import { BaseInteraction, PermissionResolvable } from "discord.js";
export default (
interaction: BaseInteraction,
permission: PermissionResolvable
) => {
if (!interaction.memberPermissions)
throw new Error("Could not check user for permissions");
if (!interaction.memberPermissions.has(permission))
throw new Error("Permission denied");
};

View file

@ -1,14 +0,0 @@
import { ChatInputCommandInteraction } from "discord.js";
import { ICommand } from "../../interfaces/Command";
export default async (
interaction: ChatInputCommandInteraction,
currentCommand: ICommand
) => {
const subcommand = interaction.options.getSubcommand();
const subcommandGroup = interaction.options.getSubcommandGroup(false);
return subcommandGroup
? currentCommand.moduleData[subcommandGroup].moduleData[subcommand].metadata
: currentCommand.moduleData[subcommand].metadata;
};

View file

@ -2,6 +2,5 @@ import { SlashCommandBuilder } from "@discordjs/builders";
export interface ICommand {
builder: SlashCommandBuilder;
moduleData: any;
execute: Promise<void>;
}

View file

@ -1,142 +0,0 @@
import { ColorResolvable } from "discord.js";
import { model, Schema } from "mongoose";
interface IGuild {
guildId: string;
credits: {
status: boolean;
rate: number;
timeout: number;
workRate: number;
minimumLength: number;
workTimeout: number;
};
embeds: {
successColor: ColorResolvable;
waitColor: ColorResolvable;
errorColor: ColorResolvable;
footerIcon: string;
footerText: string;
};
shop: { roles: { status: boolean; pricePerHour: number } };
points: {
status: boolean;
rate: number;
minimumLength: number;
timeout: number;
};
welcome: {
status: boolean;
joinChannel: string;
leaveChannel: string;
joinChannelMessage: string;
leaveChannelMessage: string;
};
audits: { status: boolean; channelId: string };
}
const guildSchema = new Schema<IGuild>(
{
guildId: {
type: String,
required: true,
unique: true,
index: true,
},
credits: {
status: {
type: Boolean,
default: true,
},
rate: {
type: Number,
default: 1,
},
minimumLength: {
type: Number,
default: 5,
},
timeout: {
type: Number,
default: 5,
},
workRate: {
type: Number,
default: 15,
},
workTimeout: {
type: Number,
default: 900,
},
},
embeds: {
successColor: {
type: String,
default: "#22bb33",
},
waitColor: {
type: String,
default: "#f0ad4e",
},
errorColor: {
type: String,
default: "#bb2124",
},
footerText: {
type: String,
default: "https://github.com/ZynerOrg/xyter",
},
footerIcon: {
type: String,
default: "https://github.com/ZynerOrg.png",
},
},
shop: {
roles: {
status: {
type: Boolean,
default: false,
},
pricePerHour: {
type: Number,
default: 5,
},
},
},
points: {
status: {
type: Boolean,
default: false,
},
rate: {
type: Number,
default: 1,
},
minimumLength: {
type: Number,
default: 5,
},
timeout: {
type: Number,
default: 5,
},
},
welcome: {
status: {
type: Boolean,
default: false,
},
joinChannel: { type: String },
leaveChannel: { type: String },
joinChannelMessage: { type: String },
leaveChannelMessage: { type: String },
},
audits: {
status: { type: Boolean, default: false },
channelId: { type: String },
},
},
{ timestamps: true }
);
export default model<IGuild>("guild", guildSchema);

View file

@ -1,48 +0,0 @@
import { Snowflake } from "discord.js";
import { model, Schema } from "mongoose";
export interface IShopRole {
roleId: Snowflake;
userId: Snowflake;
guildId: Snowflake;
pricePerHour: number;
lastPayed: Date;
}
const shopRoleSchema = new Schema<IShopRole>(
{
roleId: {
type: String,
required: true,
unique: false,
index: true,
},
userId: {
type: String,
required: true,
unique: false,
index: true,
},
guildId: {
type: String,
required: true,
unique: false,
index: true,
},
pricePerHour: {
type: Number,
required: true,
unique: false,
index: true,
default: 5,
},
lastPayed: {
type: Date,
unique: false,
index: true,
},
},
{ timestamps: true }
);
export default model<IShopRole>("shopRole", shopRoleSchema);

View file

@ -1,38 +0,0 @@
import { Snowflake } from "discord.js";
import { model, Schema } from "mongoose";
export interface ITimeout {
userId: Snowflake;
guildId: Snowflake;
cooldown: number;
timeoutId: string;
createdAt: Date;
updatedAt: Date;
}
const timeoutSchema = new Schema<ITimeout>(
{
userId: {
type: String,
required: true,
unique: false,
index: true,
},
guildId: {
type: String,
required: true,
unique: false,
index: true,
},
cooldown: {
type: Number,
required: true,
unique: false,
index: true,
},
timeoutId: { type: String },
},
{ timestamps: true }
);
export default model<ITimeout>("timeout", timeoutSchema);

View file

@ -1,42 +0,0 @@
import { Snowflake } from "discord.js";
import { model, Schema } from "mongoose";
export interface IUser {
guildId: Snowflake;
userId: Snowflake;
language: string;
reputation: number;
credits: number;
level: number;
points: number;
updatedAt: Date;
createdAt: Date;
}
const userSchema = new Schema(
{
guildId: {
type: String,
required: true,
unique: false,
index: true,
},
userId: {
type: String,
required: true,
unique: false,
index: true,
},
language: {
type: String,
default: "en",
},
reputation: { type: Number, default: 0 },
credits: { type: Number, default: 0 },
level: { type: Number, default: 0 },
points: { type: Number, default: 0 },
},
{ timestamps: true }
);
export default model<IUser>("user", userSchema);

View file

@ -1,9 +1,10 @@
import { Client } from "discord.js";
import logger from "../../../../../middlewares/logger";
import { IShopRole } from "../../../../../interfaces/ShopRole";
import { GuildShopRoles } from "@prisma/client";
export const execute = async (_client: Client, role: IShopRole) => {
// Execute the dueForPayment function
export const execute = (_client: Client, role: GuildShopRoles) => {
const { roleId } = role;
logger.silly(`Shop role ${roleId} is not due for payment.`);

View file

@ -1,22 +1,14 @@
import { Client } from "discord.js";
import logger from "../../../../../middlewares/logger";
import { IShopRole } from "../../../../../interfaces/ShopRole";
import guildSchema from "../../../../../models/guild";
import shopRoleSchema from "../../../../../models/shopRole";
import userSchema from "../../../../../models/user";
import { GuildShopRoles } from "@prisma/client";
import prisma from "../../../../../handlers/database";
// Execute the component
export const execute = async (client: Client, role: IShopRole) => {
export const execute = async (client: Client, role: GuildShopRoles) => {
const { guildId, userId, roleId } = role;
if (!userId) throw new Error("User ID not found for shop role.");
const guildData = await guildSchema.findOne({ guildId });
if (!guildData) throw new Error("Guild not found.");
const userData = await userSchema.findOne({ guildId, userId });
if (!userData) throw new Error("User not found.");
const rGuild = client.guilds.cache.get(guildId);
if (!rGuild) throw new Error("Guild not found.");
@ -28,26 +20,44 @@ export const execute = async (client: Client, role: IShopRole) => {
logger.debug(`Shop role ${roleId} is due for payment.`);
const { pricePerHour } = guildData.shop.roles;
const getGuildMember = await prisma.guildMember.findUnique({
where: {
userId_guildId: {
userId,
guildId,
},
},
include: {
user: true,
guild: true,
},
});
if (userData.credits < pricePerHour) {
logger.silly(getGuildMember);
if (!getGuildMember) throw new Error("Could not find guild member.");
const pricePerHour = getGuildMember.guild.shopRolesPricePerHour;
if (getGuildMember.creditsEarned < pricePerHour) {
await rMember.roles
.remove(roleId)
.then(async () => {
await shopRoleSchema
.deleteOne({
userId,
roleId,
guildId,
})
.then(() => {
logger.silly(
`Shop role document ${roleId} has been deleted from user ${userId}.`
);
})
.catch(() => {
throw new Error("Failed deleting shop role from user.");
});
const deleteShopRole = await prisma.guildShopRoles.delete({
where: {
guildId_userId_roleId: {
guildId,
userId,
roleId,
},
},
});
logger.silly(deleteShopRole);
logger.silly(
`Shop role document ${roleId} has been deleted from user ${userId}.`
);
})
.catch(() => {
throw new Error(`Failed removing role from user.`);
@ -56,25 +66,63 @@ export const execute = async (client: Client, role: IShopRole) => {
throw new Error("User does not have enough credits.");
}
userData.credits -= pricePerHour;
await userData
.save()
.then(async () => {
logger.silly(`User ${userId} has been updated.`);
const createGuildMember = await prisma.guildMember.upsert({
where: {
userId_guildId: {
userId,
guildId,
},
},
update: { creditsEarned: { decrement: pricePerHour } },
create: {
creditsEarned: -pricePerHour,
user: {
connectOrCreate: {
create: {
id: userId,
},
where: {
id: userId,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guildId,
},
where: {
id: guildId,
},
},
},
},
include: {
user: true,
guild: true,
},
});
role.lastPayed = new Date();
await role
.save()
.then(() => {
logger.silly(`Shop role ${roleId} has been updated.`);
})
.catch(() => {
throw new Error("Failed updating shop role.");
});
logger.silly(createGuildMember);
logger.debug(`Shop role ${roleId} has been paid.`);
})
.catch(() => {
throw new Error("Failed updating user.");
});
logger.silly(`User ${userId} has been updated.`);
const updateGuildShopRole = await prisma.guildShopRoles.update({
where: {
guildId_userId_roleId: {
guildId,
userId,
roleId,
},
},
data: {
lastPayed: new Date(),
},
});
logger.silly(updateGuildShopRole);
logger.silly(`Shop role ${roleId} has been updated.`);
logger.debug(`Shop role ${roleId} has been paid.`);
};

View file

@ -1,32 +1,28 @@
/* eslint-disable no-loops/no-loops */
import { Client } from "discord.js";
import prisma from "../../../../handlers/database";
import { IShopRole } from "../../../../interfaces/ShopRole";
import shopRoleSchema from "../../../../models/shopRole";
import * as dueForPayment from "./components/dueForPayment";
import * as overDueForPayment from "./components/overDueForPayment";
import { execute as dueForPaymentExecute } from "./components/dueForPayment";
import { execute as overDueForPaymentExecute } from "./components/overDueForPayment";
// Execute the roles function
export const execute = async (client: Client) => {
const roles = await shopRoleSchema.find();
const roles = await prisma.guildShopRoles.findMany();
await Promise.all(
roles.map(async (role: IShopRole) => {
const { lastPayed } = role;
const nextPayment = new Date(
lastPayed.setHours(lastPayed.getHours() + 1)
);
for await (const role of roles) {
const { lastPayed } = role;
const nextPayment = new Date(lastPayed.setHours(lastPayed.getHours() + 1));
const now = new Date();
const now = new Date();
if (nextPayment > now) {
await dueForPayment.execute(client, role);
if (nextPayment > now) {
dueForPaymentExecute(client, role);
return;
}
return;
}
if (nextPayment < now) {
await overDueForPayment.execute(client, role);
}
})
);
if (nextPayment < now) {
await overDueForPaymentExecute(client, role);
}
}
};

View file

@ -1,36 +1,40 @@
/* eslint-disable no-loops/no-loops */
import logger from "../../middlewares/logger";
import timeoutSchema from "../../models/timeout";
import addSeconds from "../../helpers/addSeconds";
import prisma from "../../handlers/database";
export const options = {
schedule: "*/30 * * * *", // https://crontab.guru/
};
// Execute the job
export const execute = async () => {
const timeouts = await timeoutSchema.find();
await Promise.all(
timeouts.map(async (timeout) => {
const { guildId, userId, timeoutId, cooldown, createdAt } = timeout;
const getCooldown = await prisma.cooldown.findMany();
const overDue = (await addSeconds(cooldown, createdAt)) < new Date();
for await (const timeout of getCooldown) {
const { guildId, userId, timeoutId, cooldown, createdAt } = timeout;
if (overDue) {
timeoutSchema
.deleteOne({
const overDue = (await addSeconds(cooldown, createdAt)) < new Date();
if (overDue) {
logger.info(timeout);
const deleteCooldown = await prisma.cooldown.delete({
where: {
guildId_userId_timeoutId: {
guildId,
userId,
timeoutId,
cooldown,
})
.then(() => {
logger.debug(
`Timeout document ${timeoutId} has been deleted from user ${userId}.`
);
});
}
})
);
},
},
});
logger.silly(deleteCooldown);
logger.debug(
`Timeout document ${timeoutId} has been deleted from user ${userId}.`
);
}
}
};