Merge branch 'dev' into snyk-upgrade-8f2d20d6968ccc2e7c705d12f966b527
This commit is contained in:
commit
ae3cd011e4
95 changed files with 1583 additions and 1358 deletions
|
@ -1,5 +1,16 @@
|
|||
version = 1
|
||||
|
||||
[[analyzers]]
|
||||
name = "javascript"
|
||||
enabled = true
|
||||
|
||||
[[analyzers]]
|
||||
name = "shell"
|
||||
enabled = true
|
||||
enabled = true
|
||||
|
||||
[[transformers]]
|
||||
name = "standardjs"
|
||||
enabled = true
|
||||
|
||||
[[transformers]]
|
||||
name = "prettier"
|
104
.vscode/extensions.json
vendored
104
.vscode/extensions.json
vendored
|
@ -1,52 +1,52 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"abrahamwilliam007.es7-javascript-class-snippets",
|
||||
"christian-kohler.npm-intellisense",
|
||||
"christian-kohler.path-intellisense",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"donjayamanne.githistory",
|
||||
"eamodio.gitlens",
|
||||
"esbenp.prettier-vscode",
|
||||
"github.github-vscode-theme",
|
||||
"irongeek.vscode-env",
|
||||
"xabikos.javascriptsnippets",
|
||||
"wix.vscode-import-cost",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
"visualstudioexptteam.vscodeintellicode",
|
||||
"teledemic.branch-warnings",
|
||||
"tabnine.tabnine-vscode",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"seatonjiang.gitmoji-vscode",
|
||||
"sburg.vscode-javascript-booster",
|
||||
"kisstkondoros.vscode-codemetrics",
|
||||
"mgmcdermott.vscode-language-babel",
|
||||
"mhutchie.git-graph",
|
||||
"mikestead.dotenv",
|
||||
"mongodb.mongodb-vscode",
|
||||
"ms-vscode-remote.remote-wsl-recommender",
|
||||
"ms-vscode.js-debug",
|
||||
"ms-vscode.js-debug-companion",
|
||||
"ms-vscode.references-view",
|
||||
"ms-vscode.vscode-js-profile-table",
|
||||
"pflannery.vscode-versionlens",
|
||||
"adpyke.codesnap",
|
||||
"anan.devdocstab",
|
||||
"axosoft.gitkraken-glo",
|
||||
"gruntfuggly.todo-tree",
|
||||
"kiteco.kite",
|
||||
"lkytal.pomodoro",
|
||||
"wayou.vscode-todo-highlight",
|
||||
"johnpapa.vscode-peacock",
|
||||
"stepsize.stepsize",
|
||||
"nicoespeon.abracadabra",
|
||||
"sonarsource.sonarlint-vscode",
|
||||
"nicoespeon.hocus-pocus",
|
||||
"aaron-bond.better-comments",
|
||||
"oouo-diogo-perdigao.docthis"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"abrahamwilliam007.es7-javascript-class-snippets",
|
||||
"christian-kohler.npm-intellisense",
|
||||
"christian-kohler.path-intellisense",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"donjayamanne.githistory",
|
||||
"eamodio.gitlens",
|
||||
"esbenp.prettier-vscode",
|
||||
"github.github-vscode-theme",
|
||||
"irongeek.vscode-env",
|
||||
"xabikos.javascriptsnippets",
|
||||
"wix.vscode-import-cost",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
"visualstudioexptteam.vscodeintellicode",
|
||||
"teledemic.branch-warnings",
|
||||
"tabnine.tabnine-vscode",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"seatonjiang.gitmoji-vscode",
|
||||
"sburg.vscode-javascript-booster",
|
||||
"kisstkondoros.vscode-codemetrics",
|
||||
"mgmcdermott.vscode-language-babel",
|
||||
"mhutchie.git-graph",
|
||||
"mikestead.dotenv",
|
||||
"mongodb.mongodb-vscode",
|
||||
"ms-vscode-remote.remote-wsl-recommender",
|
||||
"ms-vscode.js-debug",
|
||||
"ms-vscode.js-debug-companion",
|
||||
"ms-vscode.references-view",
|
||||
"ms-vscode.vscode-js-profile-table",
|
||||
"pflannery.vscode-versionlens",
|
||||
"adpyke.codesnap",
|
||||
"anan.devdocstab",
|
||||
"axosoft.gitkraken-glo",
|
||||
"gruntfuggly.todo-tree",
|
||||
"kiteco.kite",
|
||||
"lkytal.pomodoro",
|
||||
"wayou.vscode-todo-highlight",
|
||||
"johnpapa.vscode-peacock",
|
||||
"stepsize.stepsize",
|
||||
"nicoespeon.abracadabra",
|
||||
"sonarsource.sonarlint-vscode",
|
||||
"nicoespeon.hocus-pocus",
|
||||
"aaron-bond.better-comments",
|
||||
"oouo-diogo-perdigao.docthis"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
|
|
52
.vscode/settings.json
vendored
52
.vscode/settings.json
vendored
|
@ -1,26 +1,26 @@
|
|||
{
|
||||
"editor.bracketPairColorization.enabled": true,
|
||||
"editor.codeActionsOnSave": ["source.formatDocument", "source.fixAll.eslint"],
|
||||
"editor.cursorBlinking": "phase",
|
||||
"editor.cursorSmoothCaretAnimation": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.fontFamily": "Cascadia Code",
|
||||
"editor.fontLigatures": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.guides.bracketPairs": "active",
|
||||
"editor.minimap.maxColumn": 200,
|
||||
"editor.minimap.renderCharacters": false,
|
||||
"editor.minimap.showSlider": "always",
|
||||
"editor.tabSize": 2,
|
||||
"editor.wordWrapColumn": 100,
|
||||
"files.eol": "\n",
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"cSpell.customDictionaries": {
|
||||
"custom-dictionary-workspace": {
|
||||
"name": "custom-dictionary-workspace",
|
||||
"path": "${workspaceFolder:xyter}/.cspell/custom-dictionary-workspace.txt",
|
||||
"addWords": true,
|
||||
"scope": "workspace"
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"editor.bracketPairColorization.enabled": true,
|
||||
"editor.codeActionsOnSave": ["source.formatDocument", "source.fixAll.eslint"],
|
||||
"editor.cursorBlinking": "phase",
|
||||
"editor.cursorSmoothCaretAnimation": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.fontFamily": "Cascadia Code",
|
||||
"editor.fontLigatures": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.guides.bracketPairs": "active",
|
||||
"editor.minimap.maxColumn": 200,
|
||||
"editor.minimap.renderCharacters": false,
|
||||
"editor.minimap.showSlider": "always",
|
||||
"editor.tabSize": 2,
|
||||
"editor.wordWrapColumn": 100,
|
||||
"files.eol": "\n",
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"cSpell.customDictionaries": {
|
||||
"custom-dictionary-workspace": {
|
||||
"name": "custom-dictionary-workspace",
|
||||
"path": "${workspaceFolder:xyter}/.cspell/custom-dictionary-workspace.txt",
|
||||
"addWords": true,
|
||||
"scope": "workspace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
50
PRIVACY.md
50
PRIVACY.md
|
@ -7,54 +7,50 @@ This document entails the privacy policy and agreement that you accept when addi
|
|||
|
||||
This privacy policy applies to **Xyter**#7721 (949998000401436673)
|
||||
|
||||
|
||||
|
||||
|
||||
### Terminology
|
||||
* **Server Manager** - Anyone who has the ability to add a bot to a server or configure the bot for the server. This is usually an administrator or moderator
|
||||
* **Server Member** - Anyone who is a member of server to which one of the bots has been added
|
||||
* **Service User** - Anyone who authorizes an application (logs in) for a scope that provides additional information
|
||||
|
||||
|
||||
- **Server Manager** - Anyone who has the ability to add a bot to a server or configure the bot for the server. This is usually an administrator or moderator
|
||||
- **Server Member** - Anyone who is a member of server to which one of the bots has been added
|
||||
- **Service User** - Anyone who authorizes an application (logs in) for a scope that provides additional information
|
||||
|
||||
### Data Collected By Command
|
||||
The following items may be collected and stored when intentionally provided by a user (usually by means of a command). This data will not be collected automatically. When providing data in this way, you forego any rights to the content of the data provided.
|
||||
* Server configurations (/settings guild)
|
||||
* Data and content for automated tasks (/shop roles)
|
||||
* Locale (/settings user language)
|
||||
* Reputation (/reputation give)
|
||||
|
||||
The following items may be collected and stored when intentionally provided by a user (usually by means of a command). This data will not be collected automatically. When providing data in this way, you forego any rights to the content of the data provided.
|
||||
|
||||
- Server configurations (/settings guild)
|
||||
- Data and content for automated tasks (/shop roles)
|
||||
- Locale (/settings user language)
|
||||
- Reputation (/reputation give)
|
||||
|
||||
### Data Collected When Enabled
|
||||
|
||||
These items will be automatically collected if a bot is configured to perform certain actions by a server manager. These features are always opt-in, and thus this data will not be collected unless the corresponding feature is enabled.
|
||||
* API Token & URL (/settings guild pterodactyl)
|
||||
* Counters (/admin counter)
|
||||
|
||||
|
||||
- API Token & URL (/settings guild pterodactyl)
|
||||
- Counters (/admin counter)
|
||||
|
||||
### Data Collected Automatically
|
||||
|
||||
This data may be collected automatically. This data is used to provide statistics or history data. For any bots that collect this data, it is necessary for features of said bot.
|
||||
* Username ID (Unique identifier)
|
||||
* Guild ID (Unique identifier)
|
||||
* Any data needed for standard operation of Discord bots, such as server permissions
|
||||
* Credits (/profile view)
|
||||
* Points (/profile view)
|
||||
* Levels (/profile view)
|
||||
* Timestamps (Audit logs and all your data that we store)
|
||||
|
||||
|
||||
- Username ID (Unique identifier)
|
||||
- Guild ID (Unique identifier)
|
||||
- Any data needed for standard operation of Discord bots, such as server permissions
|
||||
- Credits (/profile view)
|
||||
- Points (/profile view)
|
||||
- Levels (/profile view)
|
||||
- Timestamps (Audit logs and all your data that we store)
|
||||
|
||||
### Data Storage
|
||||
|
||||
All stored data is kept on protected servers. While storage methods vary, most data is kept within password-protected databases such as [MongoDB Atlas](https://atlas.mongodb.com/). Please keep in mind that even with these protections, no data can ever be 100% secure. All efforts are taken to keep your data secure and private, but its absolute security cannot be guaranteed.
|
||||
|
||||
|
||||
|
||||
### Feedback
|
||||
|
||||
Feedback on Xyter bot and service is appreciated. When you submit comments, suggestions, bug reports, and any other forms of feedback, you forego any rights to the content, title, or intent of the provided feedback. Additionally, the feedback may be utilized in any way.
|
||||
|
||||
|
||||
|
||||
### Agreement
|
||||
|
||||
By adding Xyter bot to your server or using this bot or service in any way, you are consenting to the policies outlined in this document. In addition, you (the server manager) are agreeing to inform your members of the [Developer Terms of Service](https://discordapp.com/developers/docs/legal) and the contents of this document. If you, the server manager, do not agree to this document, you may remove the bot(s) from the server. If you, the server member, do not agree to this document, you may leave the server that contains the bot(s). If you, the service user, do not agree to this document, you may revoke authorization of the application(s) in your 'Authorized Apps' menu.
|
||||
|
||||
Changes to This Privacy Policy
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| Version | Supported |
|
||||
| ---------- | ------------------ |
|
||||
| 2022.4.x | :white_check_mark: |
|
||||
| < 2022.4.x | :x: |
|
||||
| < 2022.4.x | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
files:
|
||||
- source: /lang/en/*.json
|
||||
translation: /lang/%two_letters_code%/%original_file_name%
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"test":"test"
|
||||
}
|
22
package.json
22
package.json
|
@ -5,7 +5,7 @@
|
|||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"start": "nodemon | pino-pretty -i pid,hostname -t yyyy-mm-dd HH:MM:s",
|
||||
"start": "node .",
|
||||
"prettier-format": "prettier \"src/**/*.ts\" --write",
|
||||
"lint": "eslint ./src --ext .ts",
|
||||
"prepare": "husky install"
|
||||
|
@ -27,37 +27,41 @@
|
|||
"email": "vermium@zyner.org"
|
||||
},
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^0.12.0",
|
||||
"@crowdin/ota-client": "^0.7.0",
|
||||
"@discordjs/builders": "^0.13.0",
|
||||
"@discordjs/rest": "^0.4.0",
|
||||
"axios": "^0.26.0",
|
||||
"axios": "^0.27.2",
|
||||
"chance": "^1.1.8",
|
||||
"common": "^0.2.5",
|
||||
"crypto": "^1.0.1",
|
||||
"discord-api-types": "^0.32.0",
|
||||
"discord-api-types": "^0.33.0",
|
||||
"discord.js": "^13.6.0",
|
||||
"i18next": "^21.6.13",
|
||||
"i18next-async-backend": "^2.0.0",
|
||||
"i18next-http-backend": "^1.4.0",
|
||||
"i18next-resources-to-backend": "^1.0.0",
|
||||
"mongoose": "^6.2.3",
|
||||
"node-schedule": "^2.1.0",
|
||||
"ts-node": "^10.7.0",
|
||||
"tsconfig-paths": "^3.14.1",
|
||||
"tsconfig-paths": "^4.0.0",
|
||||
"typescript": "^4.6.3",
|
||||
"uuid": "^8.3.2",
|
||||
"winston-daily-rotate-file": "^4.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chance": "^1.1.3",
|
||||
"@types/node-schedule": "^1.3.2",
|
||||
"@types/node-schedule": "2.1.0",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.15.0",
|
||||
"@typescript-eslint/parser": "^5.15.0",
|
||||
"eslint": "8.13.0",
|
||||
"eslint": "8.15.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"eslint-plugin-no-loops": "^0.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"husky": "^7.0.0",
|
||||
"jest": "^27.5.1",
|
||||
"husky": "8.0.1",
|
||||
"jest": "28.0.0",
|
||||
"lint-staged": "^12.3.7",
|
||||
"prettier": "^2.6.0"
|
||||
},
|
||||
|
|
|
@ -8,13 +8,15 @@ import logger from "@logger";
|
|||
import { url } from "@config/database";
|
||||
|
||||
export default async () => {
|
||||
mongoose.connect(url).then(async (connection) => {
|
||||
logger?.info(`Connected to database: ${connection.connection.name}`);
|
||||
await mongoose.connect(url).then(async (connection) => {
|
||||
logger.info(`Connected to database: ${connection.connection.name}`);
|
||||
});
|
||||
mongoose.connection.on("error", (error) => {
|
||||
logger?.error(error);
|
||||
|
||||
mongoose.connection.on("error", async (error) => {
|
||||
logger.error(error);
|
||||
});
|
||||
mongoose.connection.on("warn", (warning) => {
|
||||
logger?.warn(warning);
|
||||
|
||||
mongoose.connection.on("warn", async (warning) => {
|
||||
logger.warn(warning);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -7,7 +7,6 @@ import fetchGuild from "@helpers/fetchGuild";
|
|||
import logger from "@logger";
|
||||
|
||||
export default {
|
||||
name: "guildCreate",
|
||||
async execute(guild: Guild) {
|
||||
const { client } = guild;
|
||||
|
||||
|
@ -15,5 +14,7 @@ export default {
|
|||
|
||||
await fetchGuild(guild);
|
||||
await updatePresence(client);
|
||||
|
||||
logger.silly(`guildCreate: ${guild}`);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -7,7 +7,6 @@ import dropGuild from "@helpers/dropGuild";
|
|||
import logger from "@logger";
|
||||
|
||||
export default {
|
||||
name: "guildDelete",
|
||||
async execute(guild: Guild) {
|
||||
const { client } = guild;
|
||||
|
||||
|
@ -15,5 +14,7 @@ export default {
|
|||
|
||||
await dropGuild(guild);
|
||||
await updatePresence(client);
|
||||
|
||||
logger.silly(`guildDelete: ${guild}`);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -20,24 +20,35 @@ export default {
|
|||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: "Member Joined",
|
||||
iconURL: member.user.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(`${member.user} ${member.user.tag}`)
|
||||
.addFields([
|
||||
{ name: "Account Age", value: `${member.user.createdAt}` },
|
||||
])
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
(channel as TextChannel)
|
||||
.send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: "Member Joined",
|
||||
iconURL: member.user.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(`${member.user} ${member.user.tag}`)
|
||||
.addFields([
|
||||
{ name: "Account Age", value: `${member.user.createdAt}` },
|
||||
])
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
})
|
||||
.then(async () => {
|
||||
logger.info(
|
||||
`Audit log sent for event guildMemberAdd in guild ${member.guild.name} (${member.guild.id})`
|
||||
);
|
||||
})
|
||||
.catch(async () => {
|
||||
logger.error(
|
||||
`Audit log failed to send for event guildMemberAdd in guild ${member.guild.name} (${member.guild.id})`
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -9,7 +9,6 @@ import joinMessage from "../guildMemberAdd/joinMessage";
|
|||
import audits from "../guildMemberAdd/audits";
|
||||
|
||||
export default {
|
||||
name: "guildMemberAdd",
|
||||
async execute(member: GuildMember) {
|
||||
const { client, user, guild } = member;
|
||||
|
||||
|
|
|
@ -20,21 +20,32 @@ export default {
|
|||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(errorColor)
|
||||
.setAuthor({
|
||||
name: "Member Left",
|
||||
iconURL: member.user.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(`${member.user} ${member.user.tag}`)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
(channel as TextChannel)
|
||||
.send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(errorColor)
|
||||
.setAuthor({
|
||||
name: "Member Left",
|
||||
iconURL: member.user.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(`${member.user} ${member.user.tag}`)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
})
|
||||
.then(async () => {
|
||||
logger.info(
|
||||
`Audit log sent for event guildMemberRemove in guild ${member.guild.name} (${member.guild.id})`
|
||||
);
|
||||
})
|
||||
.catch(async () => {
|
||||
logger.error(
|
||||
`Audit log failed to send for event guildMemberRemove in guild ${member.guild.name} (${member.guild.id})`
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -9,7 +9,6 @@ import leaveMessage from "./leaveMessage";
|
|||
import audits from "./audits";
|
||||
|
||||
export default {
|
||||
name: "guildMemberRemove",
|
||||
async execute(member: GuildMember) {
|
||||
const { client, user, guild } = member;
|
||||
|
||||
|
|
|
@ -26,23 +26,34 @@ export default {
|
|||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setDescription(
|
||||
`
|
||||
(channel as TextChannel)
|
||||
.send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setDescription(
|
||||
`
|
||||
**Interaction created by** ${interaction.user.username} **in** ${interaction.channel}
|
||||
`
|
||||
)
|
||||
.setThumbnail(interaction.user.displayAvatarURL())
|
||||
.addFields([{ name: "Event", value: "interactionCreate" }])
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
)
|
||||
.setThumbnail(interaction.user.displayAvatarURL())
|
||||
.addFields([{ name: "Event", value: "interactionCreate" }])
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
})
|
||||
.then(async () => {
|
||||
logger.info(
|
||||
`Audit log sent for event interactionCreate in guild ${interaction?.guild?.name} (${interaction?.guild?.id})`
|
||||
);
|
||||
})
|
||||
.catch(async () => {
|
||||
logger.error(
|
||||
`Audit log failed to send for event interactionCreate in guild ${interaction?.guild?.name} (${interaction?.guild?.id})`
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,16 +4,83 @@ import { CommandInteraction, MessageEmbed } from "discord.js";
|
|||
import logger from "@logger";
|
||||
|
||||
import { errorColor, footerText, footerIcon } from "@config/embed";
|
||||
import i18next from "i18next";
|
||||
import deferReply from "@root/helpers/deferReply";
|
||||
import getCommandMeta from "@root/helpers/getCommandMeta";
|
||||
|
||||
export default async (interaction: CommandInteraction) => {
|
||||
if (!interaction.isCommand()) return;
|
||||
|
||||
const { client, guild, commandName, user } = interaction;
|
||||
const { client, guild, commandName, user, memberPermissions } = interaction;
|
||||
|
||||
const currentCommand = client.commands.get(commandName);
|
||||
if (!currentCommand) return;
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
if (currentCommand == null) {
|
||||
logger.silly(`Command ${commandName} not found`);
|
||||
}
|
||||
|
||||
const meta = await getCommandMeta(interaction, currentCommand);
|
||||
|
||||
await deferReply(interaction, meta.ephemeral || false);
|
||||
|
||||
if (
|
||||
meta.permissions &&
|
||||
meta.guildOnly &&
|
||||
!memberPermissions?.has(meta.permissions)
|
||||
) {
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:toolbox:] Manage")
|
||||
.setDescription(`You do not have the permission to manage the bot.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (meta.guildOnly) {
|
||||
if (!guild) {
|
||||
logger.verbose(`Guild is null`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setDescription(
|
||||
i18next.t("guildOnly", {
|
||||
lng: interaction.locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (meta.dmOnly) {
|
||||
if (guild) {
|
||||
logger.verbose(`Guild exist`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setDescription(
|
||||
i18next.t("dmOnly", {
|
||||
lng: interaction.locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await currentCommand
|
||||
.execute(interaction)
|
||||
|
@ -23,7 +90,7 @@ export default async (interaction: CommandInteraction) => {
|
|||
);
|
||||
})
|
||||
.catch(async (error: any) => {
|
||||
logger?.error(error);
|
||||
logger?.error(`${error}`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
|
|
|
@ -7,7 +7,6 @@ import logger from "@logger";
|
|||
import audits from "./audits";
|
||||
|
||||
export default {
|
||||
name: "interactionCreate",
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { guild, id } = interaction;
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import { Message } from "discord.js";
|
|||
import modules from "@events/messageCreate/modules";
|
||||
|
||||
export default {
|
||||
name: "messageCreate",
|
||||
async execute(message: Message) {
|
||||
await modules.credits.execute(message);
|
||||
await modules.points.execute(message);
|
||||
|
|
|
@ -26,26 +26,37 @@ export default {
|
|||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: message.author.username,
|
||||
iconURL: message.author.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(
|
||||
`
|
||||
(channel as TextChannel)
|
||||
.send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: message.author.username,
|
||||
iconURL: message.author.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(
|
||||
`
|
||||
**Message sent by** ${message.author} **deleted in** ${message.channel}
|
||||
${message.content}
|
||||
`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
})
|
||||
.then(async () => {
|
||||
logger.info(
|
||||
`Audit log sent for event messageDelete in guild ${message?.guild?.name} (${message?.guild?.id})`
|
||||
);
|
||||
})
|
||||
.catch(async () => {
|
||||
logger.error(
|
||||
`Audit log failed to send for event messageDelete in guild ${message?.guild?.name} (${message?.guild?.id})`
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,7 +3,6 @@ import audits from "@events/messageDelete/audits";
|
|||
import counter from "./modules/counter";
|
||||
|
||||
export default {
|
||||
name: "messageDelete",
|
||||
async execute(message: Message) {
|
||||
await audits.execute(message);
|
||||
await counter(message);
|
||||
|
|
|
@ -29,25 +29,36 @@ export default {
|
|||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: newMessage.author.username,
|
||||
iconURL: newMessage.author.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(
|
||||
`
|
||||
(channel as TextChannel)
|
||||
.send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: newMessage.author.username,
|
||||
iconURL: newMessage.author.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(
|
||||
`
|
||||
**Message edited in** ${newMessage.channel} [jump to message](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${newMessage.id})
|
||||
`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
})
|
||||
.then(async () => {
|
||||
logger.info(
|
||||
`Audit log sent for event messageUpdate in guild ${newMessage?.guild?.name} (${newMessage?.guild?.id})`
|
||||
);
|
||||
})
|
||||
.catch(async () => {
|
||||
logger.error(
|
||||
`Audit log failed to send for event messageUpdate in guild ${newMessage?.guild?.name} (${newMessage?.guild?.id})`
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -8,7 +8,6 @@ import counter from "./modules/counter";
|
|||
import audits from "./audits";
|
||||
|
||||
export default {
|
||||
name: "messageUpdate",
|
||||
async execute(oldMessage: Message, newMessage: Message) {
|
||||
const { author, guild } = newMessage;
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import deployCommands from "@handlers/deployCommands";
|
|||
import devMode from "@handlers/devMode";
|
||||
|
||||
export default {
|
||||
name: "ready",
|
||||
once: true,
|
||||
async execute(client: Client) {
|
||||
logger.info(`${client.user?.tag} (${client.user?.id}) is ready`);
|
||||
|
|
|
@ -15,19 +15,18 @@ export default async (client: Client) => {
|
|||
plugins.map(async (pluginName) => {
|
||||
const plugin = await import(`../plugins/${pluginName}`);
|
||||
|
||||
await client?.commands?.set(
|
||||
plugin?.default?.data?.name,
|
||||
plugin?.default
|
||||
await client.commands.set(
|
||||
plugin.default.data.name,
|
||||
plugin.default,
|
||||
plugin.default.meta
|
||||
);
|
||||
|
||||
logger.verbose(`Loaded plugin: ${pluginName}`);
|
||||
})
|
||||
)
|
||||
.then(async () => {
|
||||
logger.debug("Successfully loaded plugins.");
|
||||
})
|
||||
.catch(async (err) => {
|
||||
logger.error(err);
|
||||
logger.error(`${err}`);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ import { secretKey, algorithm } from "@config/encryption";
|
|||
|
||||
const iv = crypto.randomBytes(16);
|
||||
|
||||
const encrypt = (text: any) => {
|
||||
const encrypt = (text: any): { iv: error; content: error } => {
|
||||
const cipher = crypto.createCipheriv(algorithm, secretKey, iv);
|
||||
|
||||
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]);
|
||||
|
|
|
@ -15,12 +15,12 @@ export default async (client: Client) => {
|
|||
logger.verbose(`Loaded event: ${eventName}`);
|
||||
|
||||
if (event.once) {
|
||||
return client.once(event.default.name, async (...args) =>
|
||||
return client.once(eventName, async (...args) =>
|
||||
event.default.execute(...args)
|
||||
);
|
||||
}
|
||||
|
||||
return client.on(event.default.name, async (...args) =>
|
||||
return client.on(eventName, async (...args) =>
|
||||
event.default.execute(...args)
|
||||
);
|
||||
})
|
||||
|
|
22
src/helpers/deferReply.ts
Normal file
22
src/helpers/deferReply.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { waitColor, footerText, footerIcon } from "@config/embed";
|
||||
|
||||
export default async (interaction: CommandInteraction, ephemeral: boolean) => {
|
||||
await interaction.deferReply({
|
||||
ephemeral,
|
||||
});
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
})
|
||||
.setTimestamp(new Date())
|
||||
.setTitle("Processing your request")
|
||||
.setColor(waitColor)
|
||||
.setDescription("Please wait..."),
|
||||
],
|
||||
});
|
||||
};
|
9
src/helpers/embedBuilder.ts
Normal file
9
src/helpers/embedBuilder.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { footerText, footerIcon } from "@config/embed";
|
||||
import { MessageEmbed } from "discord.js";
|
||||
|
||||
export default new MessageEmbed()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
})
|
||||
.setTimestamp(new Date());
|
12
src/helpers/getCommandMeta.ts
Normal file
12
src/helpers/getCommandMeta.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
export default async (interaction: CommandInteraction, currentCommand: any) => {
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
const subcommandGroup = interaction.options.getSubcommandGroup(false);
|
||||
|
||||
if (!subcommandGroup) {
|
||||
return currentCommand.modules[subcommand].meta;
|
||||
}
|
||||
|
||||
return currentCommand.groups[subcommandGroup].modules[subcommand].meta;
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
import logger from "@root/logger";
|
||||
|
||||
export default (count: number, noun: string, suffix?: string) => {
|
||||
export default (count: number, noun: string, suffix?: string): string => {
|
||||
const result = `${count} ${noun}${count !== 1 ? suffix || "s" : ""}`;
|
||||
logger?.verbose(`Pluralized ${count} to ${result}`);
|
||||
return result;
|
||||
|
|
55
src/index.ts
55
src/index.ts
|
@ -4,25 +4,62 @@ import { token, intents } from "@config/discord";
|
|||
|
||||
import { Client } from "discord.js"; // discord.js
|
||||
|
||||
import locale from "@locale";
|
||||
import database from "@database";
|
||||
import schedules from "@schedules";
|
||||
import events from "@handlers/events";
|
||||
import commands from "@handlers/commands";
|
||||
|
||||
async function main() {
|
||||
// Main process that starts all other sub processes
|
||||
const main = async () => {
|
||||
// Initiate client object
|
||||
const client = new Client({
|
||||
intents,
|
||||
});
|
||||
|
||||
await locale();
|
||||
await database();
|
||||
await schedules(client);
|
||||
// Start database manager
|
||||
await database()
|
||||
.then(async () => {
|
||||
await logger.silly("Database process started");
|
||||
})
|
||||
.catch(async (err) => {
|
||||
await logger.error(err);
|
||||
});
|
||||
|
||||
await commands(client);
|
||||
await events(client);
|
||||
// Start schedule manager
|
||||
await schedules(client)
|
||||
.then(async () => {
|
||||
await logger.silly("Schedules process started");
|
||||
})
|
||||
.catch(async (err) => {
|
||||
await logger.error(err);
|
||||
});
|
||||
|
||||
// Start command handler
|
||||
await commands(client)
|
||||
.then(async () => {
|
||||
await logger.silly("Commands process started");
|
||||
})
|
||||
.catch(async (err) => {
|
||||
await logger.error(err);
|
||||
});
|
||||
|
||||
// Start event handler
|
||||
await events(client)
|
||||
.then(async () => {
|
||||
await logger.silly("Events process started");
|
||||
})
|
||||
.catch(async (err) => {
|
||||
await logger.error(err);
|
||||
});
|
||||
|
||||
// Authorize with Discord's API
|
||||
await client.login(token);
|
||||
}
|
||||
};
|
||||
|
||||
main();
|
||||
await main()
|
||||
.then(async () => {
|
||||
await logger.silly("Main process started");
|
||||
})
|
||||
.catch(async (err) => {
|
||||
await logger.error(err);
|
||||
});
|
||||
|
|
|
@ -1,205 +0,0 @@
|
|||
import i18next from "i18next";
|
||||
import logger from "@logger";
|
||||
|
||||
export default async () => {
|
||||
await i18next
|
||||
.init({
|
||||
lng: "en", // if you're using a language detector, do not define the lng option
|
||||
// debug: true,
|
||||
fallbackLng: "en",
|
||||
resources: {
|
||||
en: {
|
||||
general: { not_available: "Not Available" },
|
||||
commands: {
|
||||
credits: {
|
||||
general: {
|
||||
credits_one: "{{count}} credit",
|
||||
credits_other: "{{count}} credits",
|
||||
},
|
||||
addons: {
|
||||
balance: { embed: { title: "Credits" } },
|
||||
gift: { embed: { title: "Gift" } },
|
||||
},
|
||||
},
|
||||
reputation: {
|
||||
addons: {
|
||||
give: {
|
||||
version01: {
|
||||
embed: {
|
||||
title: ":medal: Reputation",
|
||||
description:
|
||||
"You have given reputation within the last day, you can not repute now!",
|
||||
},
|
||||
},
|
||||
version02: {
|
||||
embed: {
|
||||
title: ":medal: Reputation",
|
||||
description:
|
||||
"You have given {{user}} a {{type}} reputation!",
|
||||
},
|
||||
},
|
||||
version03: {
|
||||
embed: {
|
||||
title: ":medal: Reputation",
|
||||
description: "You can not repute yourself.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
profile: {
|
||||
addons: {
|
||||
view: {
|
||||
embed: {
|
||||
title: "Profile",
|
||||
reputation: "Reputation (Global)",
|
||||
level: "Level (Guild)",
|
||||
points: "Points (Guild)",
|
||||
credits: "Credits (Guild)",
|
||||
language_code: "Language Code (Global)",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
embed: {
|
||||
title: "Profile",
|
||||
description: "Following settings is set",
|
||||
fields: { language: "Language" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sv: {
|
||||
general: { not_available: "Otillgänglig" },
|
||||
commands: {
|
||||
credits: {
|
||||
general: {
|
||||
credits_one: "{{count}} krona",
|
||||
credits_other: "{{count}} kronor",
|
||||
},
|
||||
addons: {
|
||||
balance: { embed: { title: "Krediter" } },
|
||||
gift: { embed: { title: "Gåva" } },
|
||||
},
|
||||
},
|
||||
reputation: {
|
||||
addons: {
|
||||
give: {
|
||||
version01: {
|
||||
embed: {
|
||||
title: ":medal: Omdöme",
|
||||
description:
|
||||
"Du har redan gett omdöme inom den senaste dagen, du kan inte ge ett omdöme just nu!",
|
||||
},
|
||||
},
|
||||
version02: {
|
||||
embed: {
|
||||
title: ":medal: Omdöme",
|
||||
description: "Du har gett {{user}} ett {{type}} omdöme!",
|
||||
},
|
||||
},
|
||||
version03: {
|
||||
embed: {
|
||||
title: ":medal: Omdöme",
|
||||
description: "Du kan inte ge dig själv ett omdöme.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
profile: {
|
||||
addons: {
|
||||
view: {
|
||||
embed: {
|
||||
title: "Profil",
|
||||
reputation: "Omdöme (Globalt)",
|
||||
level: "Nivå (Server)",
|
||||
points: "Poäng (Server)",
|
||||
credits: "Krediter (Server)",
|
||||
language_code: "Språkkod (Globalt)",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
embed: {
|
||||
title: "Profil",
|
||||
description: "Följande inställningar är satta",
|
||||
fields: { language: "Språk" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
de: {
|
||||
general: { not_available: "Nicht verfügbar" },
|
||||
commands: {
|
||||
credits: {
|
||||
general: {
|
||||
credits_one: "{{count}} Guthaben",
|
||||
credits_other: "{{count}} Guthaben",
|
||||
},
|
||||
addons: {
|
||||
balance: { embed: { title: "Guthaben" } },
|
||||
gift: { embed: { title: "Geschenk" } },
|
||||
},
|
||||
},
|
||||
reputation: {
|
||||
addons: {
|
||||
give: {
|
||||
version01: {
|
||||
embed: {
|
||||
title: ":medal: Ruf",
|
||||
description:
|
||||
"Du hast dir am letzten Tag einen Ruf verschafft, den du jetzt nicht rühmen kannst!",
|
||||
},
|
||||
},
|
||||
version02: {
|
||||
embed: {
|
||||
title: ":medal: Ruf",
|
||||
description:
|
||||
"Du hast {{user}} einen {{type}} Ruf gegeben!",
|
||||
},
|
||||
},
|
||||
version03: {
|
||||
embed: {
|
||||
title: ":medal: Ruf",
|
||||
description: "Du kannst dich nicht selbst rühmen.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
profile: {
|
||||
addons: {
|
||||
view: {
|
||||
embed: {
|
||||
title: "Profil",
|
||||
reputation: "Ruf (Weltweit)",
|
||||
level: "Level (Gilde)",
|
||||
points: "Punkte (Gilde)",
|
||||
credits: "Guthaben (Gilde)",
|
||||
language_code: "Sprachcode (Weltweit)",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
embed: {
|
||||
title: "Profile",
|
||||
description: "Folgende Einstellungen werden vorgenommen",
|
||||
fields: { language: "Sprache" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(async () => {
|
||||
logger.debug(`i18next initialized`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger.error(`i18next failed to initialize: ${error}`);
|
||||
});
|
||||
};
|
|
@ -3,24 +3,31 @@ import "winston-daily-rotate-file";
|
|||
|
||||
const { combine, timestamp, printf, colorize, align, json } = winston.format;
|
||||
|
||||
export default winston.createLogger({
|
||||
level: process.env.LOG_LEVEL || "silly",
|
||||
transports: [
|
||||
new winston.transports.DailyRotateFile({
|
||||
filename: "logs/combined-%DATE%.log",
|
||||
datePattern: "YYYY-MM-DD",
|
||||
maxFiles: "14d",
|
||||
format: combine(timestamp(), json()),
|
||||
}),
|
||||
new winston.transports.Console({
|
||||
format: combine(
|
||||
colorize({ all: true }),
|
||||
timestamp({
|
||||
format: "YYYY-MM-DD HH:MM:ss",
|
||||
module.exports = {
|
||||
// Logger initialized async-hronously
|
||||
logger: async () => {
|
||||
return winston.createLogger({
|
||||
level: process.env.LOG_LEVEL || "silly",
|
||||
transports: [
|
||||
new winston.transports.DailyRotateFile({
|
||||
filename: "logs/combined-%DATE%.log",
|
||||
datePattern: "YYYY-MM-DD",
|
||||
maxFiles: "14d",
|
||||
format: combine(timestamp(), json()),
|
||||
}),
|
||||
align(),
|
||||
printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`)
|
||||
),
|
||||
}),
|
||||
],
|
||||
});
|
||||
new winston.transports.Console({
|
||||
format: combine(
|
||||
colorize({ all: true }),
|
||||
timestamp({
|
||||
format: "YYYY-MM-DD HH:MM:ss",
|
||||
}),
|
||||
align(),
|
||||
printf(
|
||||
(info) => `[${info.timestamp}] ${info.level}: ${info.message}`
|
||||
)
|
||||
),
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
|
||||
import logger from "@logger";
|
||||
|
||||
import modules from "@root/plugins/counters/modules";
|
||||
import modules from "@plugins/counters/modules";
|
||||
|
||||
export default {
|
||||
metadata: { author: "Zyner" },
|
||||
modules,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("counters")
|
||||
.setDescription("View guild counters")
|
||||
|
||||
.addSubcommand(modules.view.data),
|
||||
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import view from "./view";
|
||||
import view from "@plugins/counters/modules/view";
|
||||
|
||||
export default { view };
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import { ChannelType } from "discord-api-types/v10";
|
||||
|
||||
import counterSchema from "@schemas/counter";
|
||||
|
||||
// Configuration
|
||||
import {
|
||||
errorColor,
|
||||
successColor,
|
||||
|
@ -13,7 +5,16 @@ import {
|
|||
footerIcon,
|
||||
} from "@config/embed";
|
||||
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import { ChannelType } from "discord-api-types/v10";
|
||||
|
||||
import counterSchema from "@schemas/counter";
|
||||
import i18next from "i18next";
|
||||
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: false },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("view")
|
||||
|
@ -25,14 +26,28 @@ export default {
|
|||
`The channel that contains the counter you want to view`
|
||||
)
|
||||
.setRequired(true)
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
);
|
||||
},
|
||||
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options, guild } = interaction;
|
||||
const { options, guild, locale } = interaction;
|
||||
|
||||
const discordChannel = options?.getChannel("channel");
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(
|
||||
i18next.t("counters:modules:view:general:title", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
});
|
||||
|
||||
const counter = await counterSchema?.findOne({
|
||||
guildId: guild?.id,
|
||||
channelId: discordChannel?.id,
|
||||
|
@ -41,32 +56,31 @@ export default {
|
|||
if (counter === null) {
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:1234:] Counters (View)")
|
||||
.setDescription(`No counter found for channel ${discordChannel}!`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("counters:modules:view:error01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
channel: discordChannel,
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:1234:] Counters (View)")
|
||||
embed
|
||||
.setDescription(
|
||||
`Viewing counter for channel ${discordChannel} with count ${counter.counter}.`
|
||||
i18next.t("counters:modules:view:success01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
channel: discordChannel,
|
||||
amount: counter.counter,
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1,44 +1,39 @@
|
|||
// Dependencies
|
||||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
import logger from "@logger";
|
||||
|
||||
// Modules
|
||||
import modules from "@root/plugins/credits/modules";
|
||||
import modules from "@plugins/credits/modules";
|
||||
|
||||
export default {
|
||||
metadata: { author: "Zyner" },
|
||||
modules,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("credits")
|
||||
.setDescription("Manage your credits.")
|
||||
|
||||
.addSubcommand(modules.balance.data)
|
||||
.addSubcommand(modules.gift.data)
|
||||
.addSubcommand(modules.top.data)
|
||||
.addSubcommand(modules.work.data),
|
||||
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommand() === "balance") {
|
||||
logger?.verbose(`Executing balance subcommand`);
|
||||
return modules.balance.execute(interaction);
|
||||
switch (options.getSubcommand()) {
|
||||
case "balance":
|
||||
await modules.balance.execute(interaction);
|
||||
break;
|
||||
case "gift":
|
||||
await modules.gift.execute(interaction);
|
||||
break;
|
||||
case "top":
|
||||
await modules.top.execute(interaction);
|
||||
break;
|
||||
case "work":
|
||||
await modules.work.execute(interaction);
|
||||
break;
|
||||
default:
|
||||
logger.verbose(`Unknown subcommand ${options.getSubcommand()}`);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "gift") {
|
||||
logger?.verbose(`Executing gift subcommand`);
|
||||
return modules.gift.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "top") {
|
||||
logger?.verbose(`Executing top command`);
|
||||
return modules.top.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "work") {
|
||||
logger?.verbose(`Executing work command`);
|
||||
return modules.work.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`Unknown subcommand ${options?.getSubcommand()}`);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
|
||||
import logger from "@logger";
|
||||
|
||||
// Configurations
|
||||
import {
|
||||
errorColor,
|
||||
successColor,
|
||||
|
@ -12,41 +5,53 @@ import {
|
|||
footerIcon,
|
||||
} from "@config/embed";
|
||||
|
||||
// Helpers
|
||||
import pluralize from "@helpers/pluralize";
|
||||
import i18next from "i18next";
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import logger from "@logger";
|
||||
|
||||
import fetchUser from "@helpers/fetchUser";
|
||||
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: true },
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return (
|
||||
command
|
||||
.setName("balance")
|
||||
.setDescription(`View a user's balance`)
|
||||
|
||||
// User
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription(`The user whose balance you want to view`)
|
||||
)
|
||||
);
|
||||
return command
|
||||
.setName("balance")
|
||||
.setDescription(`View a user's balance`)
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription(`The user whose balance you want to view`)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options, user, guild } = interaction;
|
||||
const { options, user, guild, locale } = interaction;
|
||||
|
||||
const discordUser = options?.getUser("user");
|
||||
const discordUser = options.getUser("user");
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(
|
||||
i18next.t("credits:modules:balance:general:title", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
if (guild === null) {
|
||||
logger?.verbose(`Guild is null`);
|
||||
logger.verbose(`Guild is null`);
|
||||
|
||||
return interaction?.editReply({
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Balance)")
|
||||
.setDescription(`You can only use this command in a guild!`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("guildOnly", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
@ -54,50 +59,55 @@ export default {
|
|||
const userObj = await fetchUser(discordUser || user, guild);
|
||||
|
||||
if (userObj === null) {
|
||||
logger?.verbose(`User not found`);
|
||||
logger.verbose(`User not found`);
|
||||
|
||||
return interaction?.editReply({
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Balance)")
|
||||
.setDescription(`Could not find user ${discordUser || user}`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("userNotFound", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
user: discordUser || user,
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (userObj.credits === null) {
|
||||
logger?.verbose(`User has no credits`);
|
||||
logger.verbose(`User has no credits`);
|
||||
|
||||
return interaction?.editReply({
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Balance)")
|
||||
.setDescription(`${discordUser || user} has no credits!`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("credits:modules:balance:error01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
user: discordUser || user,
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
logger?.verbose(`Found user ${discordUser || user}`);
|
||||
logger.verbose(`Found user ${discordUser || user}`);
|
||||
|
||||
return interaction?.editReply({
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Balance)")
|
||||
embed
|
||||
.setDescription(
|
||||
`${discordUser || user} has ${pluralize(
|
||||
userObj.credits,
|
||||
`credit`
|
||||
)}!`
|
||||
i18next.t("credits:modules:balance:success01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
user: discordUser || user,
|
||||
amount: userObj.credits,
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
},
|
||||
|
|
|
@ -18,9 +18,12 @@ import saveUser from "@helpers/saveUser";
|
|||
// Models
|
||||
import fetchUser from "@helpers/fetchUser";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import i18next from "i18next";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: true },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("gift")
|
||||
|
@ -42,38 +45,52 @@ export default {
|
|||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options, user, guild, client } = interaction;
|
||||
const { options, user, guild, client, locale } = interaction;
|
||||
|
||||
const optionUser = options?.getUser("user");
|
||||
const optionAmount = options?.getInteger("amount");
|
||||
const optionReason = options?.getString("reason");
|
||||
const optionUser = options.getUser("user");
|
||||
const optionAmount = options.getInteger("amount");
|
||||
const optionReason = options.getString("reason");
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(
|
||||
i18next.t("credits:modules:gift:general:title", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
if (guild === null) {
|
||||
logger?.verbose(`Guild is null`);
|
||||
logger.verbose(`Guild is null`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
.setDescription(`We can not find your guild!`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("guildOnly", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (optionUser === null) {
|
||||
logger?.verbose(`User not found`);
|
||||
logger.verbose(`User not found`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
.setDescription(`We can not find your requested user!`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("userNotFound", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
@ -85,119 +102,126 @@ export default {
|
|||
const toUserDB = await fetchUser(optionUser, guild);
|
||||
|
||||
if (fromUserDB === null) {
|
||||
logger?.verbose(`User not found`);
|
||||
logger.verbose(`User not found`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
embed
|
||||
.setDescription(
|
||||
`We can not find your requested from user in our database!`
|
||||
i18next.t("userNotFound", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (toUserDB === null) {
|
||||
logger?.verbose(`User not found`);
|
||||
logger.verbose(`User not found`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
embed
|
||||
.setDescription(
|
||||
`We can not find your requested to user in our database!`
|
||||
i18next.t("userNotFound", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// If receiver is same as sender
|
||||
if (optionUser?.id === user?.id) {
|
||||
logger?.verbose(`User is same as sender`);
|
||||
if (optionUser.id === user.id) {
|
||||
logger.verbose(`User is same as sender`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
.setDescription(`You can not pay yourself!`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("credits:modules:gift:error01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// If amount is null
|
||||
if (optionAmount === null) {
|
||||
logger?.verbose(`Amount is null`);
|
||||
logger.verbose(`Amount is null`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
.setDescription(`We could not read your requested amount!`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("amountNotFound", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// If amount is zero or below
|
||||
if (optionAmount <= 0) {
|
||||
logger?.verbose(`Amount is zero or below`);
|
||||
logger.verbose(`Amount is zero or below`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
.setDescription(`You can't gift zero or below!`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("credits:modules:gift:error02:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// If user has below gifting amount
|
||||
if (fromUserDB?.credits < optionAmount) {
|
||||
logger?.verbose(`User has below gifting amount`);
|
||||
if (fromUserDB.credits < optionAmount) {
|
||||
logger.verbose(`User has below gifting amount`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
embed
|
||||
.setDescription(
|
||||
`You have insufficient credits. Your balance is ${fromUserDB?.credits}!`
|
||||
i18next.t("credits:modules:gift:error03:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
amount: fromUserDB.credits,
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// If toUserDB has no credits
|
||||
if (toUserDB === null) {
|
||||
logger?.verbose(`User has no credits`);
|
||||
logger.verbose(`User has no credits`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
embed
|
||||
.setDescription(
|
||||
`We can not find your requested to user in our database!`
|
||||
i18next.t("userNotFound", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
@ -209,46 +233,50 @@ export default {
|
|||
toUserDB.credits += optionAmount;
|
||||
|
||||
// Save users
|
||||
await saveUser(fromUserDB, toUserDB)?.then(async () => {
|
||||
await saveUser(fromUserDB, toUserDB).then(async () => {
|
||||
// Get DM user object
|
||||
const dmUser = client?.users?.cache?.get(optionUser?.id);
|
||||
const dmUser = client.users.cache.get(optionUser.id);
|
||||
|
||||
if (dmUser == null) return;
|
||||
|
||||
// Send DM to user
|
||||
await dmUser
|
||||
?.send({
|
||||
.send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
embed
|
||||
.setDescription(
|
||||
`You have received ${optionAmount} credits from ${
|
||||
user?.tag
|
||||
} with reason ${
|
||||
optionReason ? ` with reason: ${optionReason}` : ""
|
||||
}!`
|
||||
i18next.t("credits:modules:gift:error03:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
user: user.tag,
|
||||
amount: optionAmount,
|
||||
reason: optionReason || "unspecified",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(successColor),
|
||||
],
|
||||
})
|
||||
.catch(async (error) =>
|
||||
logger?.error(`[Gift] Error sending DM to user: ${error}`)
|
||||
logger.error(`[Gift] Error sending DM to user: ${error}`)
|
||||
);
|
||||
|
||||
logger?.verbose(
|
||||
`[Gift] Successfully gifted ${optionAmount} credits to ${optionUser?.tag}`
|
||||
logger.verbose(
|
||||
`[Gift] Successfully gifted ${optionAmount} credits to ${optionUser.tag}`
|
||||
);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Gift)")
|
||||
embed
|
||||
.setDescription(
|
||||
`Successfully gifted ${optionAmount} credits to ${optionUser?.tag}!`
|
||||
i18next.t("credits:modules:gift:success02:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
user: user,
|
||||
amount: optionAmount,
|
||||
reason: optionReason || "unspecified",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import balance from "./balance";
|
||||
import gift from "./gift";
|
||||
import top from "./top";
|
||||
import work from "./work";
|
||||
import balance from "@plugins/credits/modules/balance";
|
||||
import gift from "@plugins/credits/modules/gift";
|
||||
import top from "@plugins/credits/modules/top";
|
||||
import work from "@plugins/credits/modules/work";
|
||||
|
||||
export default { balance, gift, top, work };
|
||||
|
|
|
@ -1,48 +1,86 @@
|
|||
// Dependencies
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import {
|
||||
successColor,
|
||||
errorColor,
|
||||
footerText,
|
||||
footerIcon,
|
||||
} from "@config/embed";
|
||||
|
||||
import i18next from "i18next";
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import logger from "@logger";
|
||||
|
||||
import userSchema from "@schemas/user";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
||||
// Helpers
|
||||
import pluralize from "@helpers/pluralize";
|
||||
import userSchema, { IUser } from "@schemas/user";
|
||||
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: false },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command.setName("top").setDescription(`View the top users`);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
// Get all users in the guild
|
||||
const { locale, guild } = interaction;
|
||||
|
||||
const usersDB = await userSchema.find({ guildId: interaction?.guild?.id });
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(
|
||||
i18next.t("credits:modules:top:general:title", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
if (guild === null) {
|
||||
logger.verbose(`Guild is null`);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("guildOnly", {
|
||||
lng: locale,
|
||||
ns: "errors",
|
||||
})
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
const usersDB = await userSchema.find({ guildId: guild.id });
|
||||
|
||||
const topTen = usersDB
|
||||
|
||||
// Sort them after credits amount (ascending)
|
||||
.sort((a, b) => (a?.credits > b?.credits ? -1 : 1))
|
||||
.sort((a, b) => (a.credits > b.credits ? -1 : 1))
|
||||
|
||||
// Return the top 10
|
||||
.slice(0, 10);
|
||||
|
||||
// Create entry object
|
||||
const entry = (x: any, index: number) =>
|
||||
`${index + 1}. <@${x?.userId}> - ${pluralize(x?.credits, "credit")}`;
|
||||
const entry = (x: IUser, index: number) =>
|
||||
i18next.t("credits:modules:top:entry", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
index: index + 1,
|
||||
user: x.userId,
|
||||
amount: x.credits,
|
||||
});
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Top)")
|
||||
embed
|
||||
.setDescription(
|
||||
`Top 10 users with the most credits.
|
||||
` ${i18next.t("credits:modules:top:success01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})}
|
||||
|
||||
${topTen.map(entry).join("\n")}`
|
||||
${topTen.map(entry).join("\n")}
|
||||
`
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
},
|
||||
|
|
|
@ -4,7 +4,12 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
import Chance from "chance";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
import {
|
||||
successColor,
|
||||
errorColor,
|
||||
footerText,
|
||||
footerIcon,
|
||||
} from "@config/embed";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
@ -15,14 +20,30 @@ import timeoutSchema from "@schemas/timeout";
|
|||
// Helpers
|
||||
import fetchUser from "@helpers/fetchUser";
|
||||
import fetchGuild from "@helpers/fetchGuild";
|
||||
import i18next from "i18next";
|
||||
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: true },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command.setName("work").setDescription(`Work to earn credits`);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
// Destructure member
|
||||
const { guild, user } = interaction;
|
||||
const { guild, user, locale } = interaction;
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(
|
||||
i18next.t("credits:modules:work:general:title", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
});
|
||||
|
||||
// Chance module
|
||||
const chance = new Chance();
|
||||
|
@ -46,14 +67,15 @@ export default {
|
|||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Work)")
|
||||
embed
|
||||
.setDescription(
|
||||
`You can not work while on timeout, please wait ${guildDB?.credits.workTimeout} seconds.`
|
||||
i18next.t("credits:modules:work:error01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
time: guildDB?.credits.workTimeout,
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
@ -78,12 +100,16 @@ export default {
|
|||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:dollar:] Credits (Work)")
|
||||
.setDescription(`You worked and earned ${creditsEarned} credits`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("credits:modules:work:success01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
time: guildDB?.credits.workTimeout,
|
||||
amount: creditsEarned,
|
||||
})
|
||||
)
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
|
27
src/plugins/fun/index.ts
Normal file
27
src/plugins/fun/index.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import logger from "@logger";
|
||||
|
||||
import modules from "@plugins/fun/modules";
|
||||
|
||||
export default {
|
||||
modules,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("fun")
|
||||
.setDescription("Fun commands.")
|
||||
|
||||
.addSubcommand(modules.meme.data),
|
||||
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
||||
switch (options.getSubcommand()) {
|
||||
case "meme":
|
||||
await modules.meme.execute(interaction);
|
||||
break;
|
||||
default:
|
||||
logger.verbose(`Unknown subcommand ${options.getSubcommand()}`);
|
||||
}
|
||||
},
|
||||
};
|
5
src/plugins/fun/modules/index.ts
Normal file
5
src/plugins/fun/modules/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import meme from "@plugins/fun/modules/meme";
|
||||
|
||||
export default {
|
||||
meme,
|
||||
};
|
37
src/plugins/fun/modules/meme.ts
Normal file
37
src/plugins/fun/modules/meme.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
||||
import axios from "axios";
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import logger from "@logger";
|
||||
|
||||
export default {
|
||||
meta: { guildOnly: false, ephemeral: false },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command.setName("meme").setDescription("Get a meme from r/memes)");
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
await axios
|
||||
.get("https://www.reddit.com/r/memes/random/.json")
|
||||
.then(async (res) => {
|
||||
const response = res.data[0].data.children;
|
||||
const content = response[0].data;
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(content.title)
|
||||
.setTimestamp(new Date())
|
||||
.setImage(content.url)
|
||||
.setFooter({
|
||||
text: `👍 ${content.ups}︱👎 ${content.downs}\n${footerText}`,
|
||||
iconURL: footerIcon,
|
||||
})
|
||||
.setColor(successColor);
|
||||
|
||||
return interaction.editReply({ embeds: [embed] });
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error(`${error}`);
|
||||
});
|
||||
},
|
||||
};
|
|
@ -5,31 +5,33 @@ import { CommandInteraction } from "discord.js";
|
|||
import logger from "@logger";
|
||||
|
||||
// Modules
|
||||
import moduleCreate from "./modules/create";
|
||||
import moduleDelete from "./modules/delete";
|
||||
import modules from "./modules";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
modules,
|
||||
|
||||
data: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("counters")
|
||||
.setDescription("Manage guild counters.")
|
||||
.addSubcommand(moduleCreate.data)
|
||||
.addSubcommand(moduleDelete.data);
|
||||
.addSubcommand(modules.add.data)
|
||||
.addSubcommand(modules.remove.data);
|
||||
},
|
||||
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommand() === "create") {
|
||||
if (options?.getSubcommand() === "add") {
|
||||
logger?.verbose(`Executing create subcommand`);
|
||||
|
||||
return moduleCreate.execute(interaction);
|
||||
return modules.add.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "delete") {
|
||||
if (options?.getSubcommand() === "remove") {
|
||||
logger?.verbose(`Executing delete subcommand`);
|
||||
|
||||
return moduleDelete.execute(interaction);
|
||||
return modules.remove.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`Unknown subcommand ${options?.getSubcommand()}`);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { MessageEmbed, CommandInteraction } from "discord.js";
|
||||
import { MessageEmbed, CommandInteraction, Permissions } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import { ChannelType } from "discord-api-types/v10";
|
||||
|
||||
|
@ -16,19 +16,26 @@ import logger from "@logger";
|
|||
|
||||
// Models
|
||||
import counterSchema from "@schemas/counter";
|
||||
import i18next from "i18next";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("create")
|
||||
.setName("add")
|
||||
.setDescription("Add a counter to your guild.")
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("The channel to send the counter to.")
|
||||
.setRequired(true)
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
|
@ -43,12 +50,22 @@ export default {
|
|||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options, guild } = interaction;
|
||||
const { options, guild, locale } = interaction;
|
||||
|
||||
const discordChannel = options?.getChannel("channel");
|
||||
const countingWord = options?.getString("word");
|
||||
const startValue = options?.getNumber("start");
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(
|
||||
i18next.t("manage:groups:counters:modules:add:general:title", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
const counter = await counterSchema?.findOne({
|
||||
guildId: guild?.id,
|
||||
channelId: discordChannel?.id,
|
||||
|
@ -57,12 +74,18 @@ export default {
|
|||
if (counter) {
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:toolbox:] Manage - Counters (Create)")
|
||||
.setDescription(`A counter already exists for this channel.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t(
|
||||
"manage:groups:counters:modules:add:error01:description",
|
||||
{
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
channel: discordChannel,
|
||||
}
|
||||
)
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
@ -79,12 +102,18 @@ export default {
|
|||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:toolbox:] Manage - Counters (Create)")
|
||||
.setDescription(`Created counter for ${discordChannel}`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t(
|
||||
"manage:groups:counters:modules:create:success01:description",
|
||||
{
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
channel: discordChannel,
|
||||
}
|
||||
)
|
||||
)
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
});
|
4
src/plugins/manage/groups/counters/modules/index.ts
Normal file
4
src/plugins/manage/groups/counters/modules/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
import add from "@plugins/manage/groups/counters/modules/add";
|
||||
import remove from "@plugins/manage/groups/counters/modules/remove";
|
||||
|
||||
export default { add, remove };
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import {
|
||||
|
@ -16,26 +16,43 @@ import logger from "@logger";
|
|||
import counterSchema from "@schemas/counter";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import { ChannelType } from "discord-api-types/v10";
|
||||
import i18next from "i18next";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("delete")
|
||||
.setName("remove")
|
||||
.setDescription(`Delete a counter from your guild.`)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("The channel to delete the counter from.")
|
||||
.setRequired(true)
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options, guild } = interaction;
|
||||
const { options, guild, locale } = interaction;
|
||||
|
||||
const discordChannel = options?.getChannel("channel");
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(
|
||||
i18next.t("manage:groups:counters:modules:remove:general:title", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
const counter = await counterSchema?.findOne({
|
||||
guildId: guild?.id,
|
||||
channelId: discordChannel?.id,
|
||||
|
@ -46,12 +63,17 @@ export default {
|
|||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:toolbox:] Manage - Counters (Delete)")
|
||||
.setDescription(`The counter for this channel does not exist.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t(
|
||||
"manage:groups:counters:modules:remove:error01:description",
|
||||
{
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
}
|
||||
)
|
||||
)
|
||||
.setColor(errorColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
@ -66,12 +88,17 @@ export default {
|
|||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:toolbox:] Manage - Counters (Delete)")
|
||||
.setDescription(`The counter for this channel has been deleted.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t(
|
||||
"manage:groups:counters:modules:remove:success01:description",
|
||||
{
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
}
|
||||
)
|
||||
)
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
})
|
|
@ -1,53 +1,43 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
|
||||
|
||||
import logger from "@logger";
|
||||
|
||||
// Modules
|
||||
import moduleGive from "./modules/give";
|
||||
import moduleSet from "./modules/set";
|
||||
import moduleTake from "./modules/take";
|
||||
import moduleTransfer from "./modules/transfer";
|
||||
import modules from "./modules";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
modules,
|
||||
|
||||
data: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("credits")
|
||||
.setDescription("Manage the credits of a user.")
|
||||
.addSubcommand(moduleGive.data)
|
||||
.addSubcommand(moduleSet.data)
|
||||
.addSubcommand(moduleTake.data)
|
||||
.addSubcommand(moduleTransfer.data);
|
||||
.addSubcommand(modules.give.data)
|
||||
.addSubcommand(modules.set.data)
|
||||
.addSubcommand(modules.take.data)
|
||||
.addSubcommand(modules.transfer.data);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommand() === "give") {
|
||||
logger?.verbose(`Executing give subcommand`);
|
||||
switch (options.getSubcommand()) {
|
||||
case "give":
|
||||
logger.verbose(`Executing give subcommand`);
|
||||
|
||||
return moduleGive.execute(interaction);
|
||||
return modules.give.execute(interaction);
|
||||
case "set":
|
||||
logger.verbose(`Executing set subcommand`);
|
||||
|
||||
return modules.set.execute(interaction);
|
||||
case "take":
|
||||
logger.verbose(`Executing take subcommand`);
|
||||
|
||||
return modules.take.execute(interaction);
|
||||
case "transfer":
|
||||
logger.verbose(`Executing transfer subcommand`);
|
||||
|
||||
return modules.transfer.execute(interaction);
|
||||
default:
|
||||
logger.verbose(`Unknown subcommand ${options.getSubcommand()}`);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "set") {
|
||||
logger?.verbose(`Executing set subcommand`);
|
||||
|
||||
return moduleSet.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "take") {
|
||||
logger?.verbose(`Executing take subcommand`);
|
||||
|
||||
return moduleTake.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "transfer") {
|
||||
logger?.verbose(`Executing transfer subcommand`);
|
||||
|
||||
return moduleTransfer.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`No subcommand found`);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
|
||||
// Configurations
|
||||
|
@ -21,6 +21,12 @@ import fetchUser from "@helpers/fetchUser";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("give")
|
||||
|
|
6
src/plugins/manage/groups/credits/modules/index.ts
Normal file
6
src/plugins/manage/groups/credits/modules/index.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import give from "@plugins/manage/groups/credits/modules/give";
|
||||
import set from "@plugins/manage/groups/credits/modules/set";
|
||||
import take from "@plugins/manage/groups/credits/modules/take";
|
||||
import transfer from "@plugins/manage/groups/credits/modules/transfer";
|
||||
|
||||
export default { give, set, take, transfer };
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import {
|
||||
|
@ -20,6 +20,12 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("set")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import {
|
||||
|
@ -21,6 +21,12 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("take")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import {
|
||||
|
@ -21,6 +21,12 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("transfer")
|
||||
|
|
4
src/plugins/manage/groups/index.ts
Normal file
4
src/plugins/manage/groups/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
import counters from "@plugins/manage/groups/counters";
|
||||
import credits from "@plugins/manage/groups/credits";
|
||||
|
||||
export default { counters, credits };
|
|
@ -1,52 +1,35 @@
|
|||
//Dependencies
|
||||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
import { CommandInteraction, Permissions, MessageEmbed } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { errorColor, footerText, footerIcon } from "@config/embed";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Groups
|
||||
import credits from "./groups/credits";
|
||||
import counters from "./groups/counters";
|
||||
import groups from "@plugins/manage/groups";
|
||||
import logger from "@logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
metadata: { author: "Zyner" },
|
||||
groups,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("manage")
|
||||
.setDescription("Manage the bot.")
|
||||
.addSubcommandGroup(counters.data)
|
||||
.addSubcommandGroup(credits.data),
|
||||
.addSubcommandGroup(groups.counters.data)
|
||||
.addSubcommandGroup(groups.credits.data),
|
||||
|
||||
async execute(interaction: CommandInteraction) {
|
||||
// Destructure
|
||||
const { memberPermissions, options } = interaction;
|
||||
|
||||
// Check permission
|
||||
if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) {
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setTitle("[:toolbox:] Manage")
|
||||
.setDescription(`You do not have the permission to manage the bot.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
}
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommandGroup() === "credits") {
|
||||
logger?.verbose(`Subcommand group is credits`);
|
||||
|
||||
return credits.execute(interaction);
|
||||
return groups.credits.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommandGroup() === "counters") {
|
||||
logger?.verbose(`Subcommand group is counters`);
|
||||
|
||||
return counters.execute(interaction);
|
||||
return groups.counters.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`Subcommand group is not credits or counters`);
|
||||
|
|
|
@ -3,34 +3,26 @@ import { SlashCommandBuilder } from "@discordjs/builders";
|
|||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import view from "./modules/view";
|
||||
import modules from "@plugins/profile/modules";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
metadata: { author: "Zyner" },
|
||||
modules,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("profile")
|
||||
.setDescription("Check a profile.")
|
||||
.addSubcommand((subcommand) =>
|
||||
subcommand
|
||||
.setName("view")
|
||||
.setDescription("View a profile.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("target")
|
||||
.setDescription("The profile you wish to view")
|
||||
)
|
||||
),
|
||||
.addSubcommand(modules.view.data),
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommand() === "view") {
|
||||
logger?.verbose(`Executing view subcommand`);
|
||||
|
||||
return view(interaction);
|
||||
return modules.view.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`No subcommand found`);
|
||||
|
|
3
src/plugins/profile/modules/index.ts
Normal file
3
src/plugins/profile/modules/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import view from "@plugins/profile/modules/view";
|
||||
|
||||
export default { view };
|
|
@ -8,68 +8,82 @@ import { successColor, footerText, footerIcon } from "@config/embed";
|
|||
import fetchUser from "@helpers/fetchUser";
|
||||
|
||||
import logger from "@logger";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
|
||||
// Function
|
||||
export default async (interaction: CommandInteraction) => {
|
||||
// Destructure
|
||||
const { client, options, user, guild } = interaction;
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: false },
|
||||
|
||||
// Target information
|
||||
const target = options?.getUser("target");
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("view")
|
||||
.setDescription("View a profile.")
|
||||
.addUserOption((option) =>
|
||||
option.setName("target").setDescription("The profile you wish to view")
|
||||
);
|
||||
},
|
||||
|
||||
// Discord User Information
|
||||
const discordUser = await client?.users?.fetch(
|
||||
`${target ? target?.id : user?.id}`
|
||||
);
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
// Destructure
|
||||
const { client, options, user, guild } = interaction;
|
||||
|
||||
if (guild === null) {
|
||||
return logger?.verbose(`Guild is null`);
|
||||
}
|
||||
// Target information
|
||||
const target = options?.getUser("target");
|
||||
|
||||
// User Information
|
||||
const userObj = await fetchUser(discordUser, guild);
|
||||
// Discord User Information
|
||||
const discordUser = await client?.users?.fetch(
|
||||
`${target ? target?.id : user?.id}`
|
||||
);
|
||||
|
||||
// Embed object
|
||||
const embed = {
|
||||
author: {
|
||||
name: `${discordUser?.username}#${discordUser?.discriminator}`,
|
||||
icon_url: discordUser?.displayAvatarURL(),
|
||||
},
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: `:dollar: Credits`,
|
||||
value: `${userObj?.credits || "Not found"}`,
|
||||
inline: true,
|
||||
if (guild === null) {
|
||||
return logger?.verbose(`Guild is null`);
|
||||
}
|
||||
|
||||
// User Information
|
||||
const userObj = await fetchUser(discordUser, guild);
|
||||
|
||||
// Embed object
|
||||
const embed = {
|
||||
author: {
|
||||
name: `${discordUser?.username}#${discordUser?.discriminator}`,
|
||||
icon_url: discordUser?.displayAvatarURL(),
|
||||
},
|
||||
{
|
||||
name: `:squeeze_bottle: Level`,
|
||||
value: `${userObj?.level || "Not found"}`,
|
||||
inline: true,
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: `:dollar: Credits`,
|
||||
value: `${userObj?.credits || "Not found"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `:squeeze_bottle: Level`,
|
||||
value: `${userObj?.level || "Not found"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `:squeeze_bottle: Points`,
|
||||
value: `${userObj?.points || "Not found"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `:loudspeaker: Reputation`,
|
||||
value: `${userObj?.reputation || "Not found"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `:rainbow_flag: Language`,
|
||||
value: `${userObj?.language || "Not found"}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
},
|
||||
{
|
||||
name: `:squeeze_bottle: Points`,
|
||||
value: `${userObj?.points || "Not found"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `:loudspeaker: Reputation`,
|
||||
value: `${userObj?.reputation || "Not found"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `:rainbow_flag: Language`,
|
||||
value: `${userObj?.language || "Not found"}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// Return interaction reply
|
||||
return interaction?.editReply({ embeds: [embed] });
|
||||
// Return interaction reply
|
||||
return interaction?.editReply({ embeds: [embed] });
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,25 +3,25 @@ import { SlashCommandBuilder } from "@discordjs/builders";
|
|||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import give from "./modules/give";
|
||||
import modules from "./modules";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
metadata: { author: "Zyner" },
|
||||
modules,
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("reputation")
|
||||
.setDescription("Manage reputation.")
|
||||
.addSubcommand(give.data),
|
||||
.addSubcommand(modules.give.data),
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommand() === "give") {
|
||||
logger?.verbose(`Executing give subcommand`);
|
||||
|
||||
await give.execute(interaction);
|
||||
await modules.give.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`No subcommand found`);
|
||||
|
|
|
@ -21,6 +21,8 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: true },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("give")
|
||||
|
@ -36,8 +38,13 @@ export default {
|
|||
.setName("type")
|
||||
.setDescription("What type of reputation you want to repute")
|
||||
.setRequired(true)
|
||||
.addChoice("Positive", "positive")
|
||||
.addChoice("Negative", "negative")
|
||||
.addChoices(
|
||||
{ name: "Positive", value: "positive" },
|
||||
{
|
||||
name: "Negative",
|
||||
value: "negative",
|
||||
}
|
||||
)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
|
|
3
src/plugins/reputation/modules/index.ts
Normal file
3
src/plugins/reputation/modules/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import give from "@plugins/reputation/modules/give";
|
||||
|
||||
export default { give };
|
60
src/plugins/settings/groups/guild/index.ts
Normal file
60
src/plugins/settings/groups/guild/index.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
||||
// Modules
|
||||
import modules from "./modules";
|
||||
|
||||
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
modules,
|
||||
|
||||
data: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("guild")
|
||||
.setDescription("Guild settings.")
|
||||
.addSubcommand(modules.pterodactyl.data)
|
||||
.addSubcommand(modules.credits.data)
|
||||
.addSubcommand(modules.points.data)
|
||||
.addSubcommand(modules.welcome.data)
|
||||
.addSubcommand(modules.audits.data)
|
||||
.addSubcommand(modules.shop.data);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
// Destructure member
|
||||
const { options } = interaction;
|
||||
|
||||
switch (options?.getSubcommand()) {
|
||||
case "pterodactyl":
|
||||
logger?.verbose(`Subcommand is pterodactyl`);
|
||||
|
||||
return modules.pterodactyl.execute(interaction);
|
||||
case "credits":
|
||||
logger?.verbose(`Subcommand is credits`);
|
||||
|
||||
return modules.credits.execute(interaction);
|
||||
case "points":
|
||||
logger?.verbose(`Subcommand is points`);
|
||||
|
||||
return modules.points.execute(interaction);
|
||||
case "welcome":
|
||||
logger?.verbose(`Subcommand is welcome`);
|
||||
|
||||
return modules.welcome.execute(interaction);
|
||||
case "audits":
|
||||
logger?.verbose(`Subcommand is audits`);
|
||||
|
||||
return modules.audits.execute(interaction);
|
||||
case "shop":
|
||||
logger?.verbose(`Subcommand is shop`);
|
||||
|
||||
return modules.shop.execute(interaction);
|
||||
default:
|
||||
logger?.verbose(`Subcommand is not found`);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { CommandInteraction, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
@ -14,6 +14,12 @@ import { ChannelType } from "discord-api-types/v10";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("audits")
|
||||
|
@ -25,7 +31,7 @@ export default {
|
|||
option
|
||||
.setName("channel")
|
||||
.setDescription("Channel for audit messages.")
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { CommandInteraction, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
@ -13,6 +13,12 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("credits")
|
8
src/plugins/settings/groups/guild/modules/index.ts
Normal file
8
src/plugins/settings/groups/guild/modules/index.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import audits from "@plugins/settings/groups/guild/modules/audits";
|
||||
import credits from "@plugins/settings/groups/guild/modules/credits";
|
||||
import points from "@plugins/settings/groups/guild/modules/points";
|
||||
import pterodactyl from "@plugins/settings/groups/guild/modules/pterodactyl";
|
||||
import shop from "@plugins/settings/groups/guild/modules/shop";
|
||||
import welcome from "@plugins/settings/groups/guild/modules/welcome";
|
||||
|
||||
export default { audits, credits, points, pterodactyl, shop, welcome };
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { CommandInteraction, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
@ -13,6 +13,12 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("points")
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { CommandInteraction, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
@ -14,6 +14,12 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("pterodactyl")
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { CommandInteraction, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
@ -10,10 +10,15 @@ import logger from "@logger";
|
|||
// Models
|
||||
import guildSchema from "@schemas/guild";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import { ChannelType } from "discord-api-types/v10";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("shop")
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { CommandInteraction, Permissions } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
@ -14,6 +14,12 @@ import { ChannelType } from "discord-api-types/v10";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: {
|
||||
guildOnly: true,
|
||||
ephemeral: true,
|
||||
permissions: [Permissions.FLAGS.MANAGE_GUILD],
|
||||
},
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("welcome")
|
||||
|
@ -25,14 +31,16 @@ export default {
|
|||
option
|
||||
.setName("join-channel")
|
||||
.setDescription("Channel for join messages.")
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
)
|
||||
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("leave-channel")
|
||||
.setDescription("Channel for leave messages.")
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
)
|
||||
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("leave-message")
|
3
src/plugins/settings/groups/index.ts
Normal file
3
src/plugins/settings/groups/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import guild from "@plugins/settings/groups/guild";
|
||||
|
||||
export default { guild };
|
|
@ -1,94 +0,0 @@
|
|||
// Dependencies
|
||||
import { Permissions, CommandInteraction } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { errorColor, footerText, footerIcon } from "@config/embed";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
||||
// Modules
|
||||
import pterodactyl from "./modules/pterodactyl";
|
||||
import credits from "./modules/credits";
|
||||
import points from "./modules/points";
|
||||
import welcome from "./modules/welcome";
|
||||
import audits from "./modules/audits";
|
||||
import shop from "./modules/shop";
|
||||
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
data: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("guild")
|
||||
.setDescription("Guild settings.")
|
||||
.addSubcommand(pterodactyl.data)
|
||||
.addSubcommand(credits.data)
|
||||
.addSubcommand(points.data)
|
||||
.addSubcommand(welcome.data)
|
||||
.addSubcommand(audits.data)
|
||||
.addSubcommand(shop.data);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
// Destructure member
|
||||
const { memberPermissions, options } = interaction;
|
||||
|
||||
// Check permission
|
||||
if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) {
|
||||
logger?.verbose(`User does not have permission to execute command.`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
{
|
||||
title: ":tools: Settings - Guild",
|
||||
color: errorColor,
|
||||
description: "You do not have permission to use this command.",
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
iconURL: footerIcon as string,
|
||||
text: footerText as string,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "pterodactyl") {
|
||||
logger?.verbose(`Executing pterodactyl subcommand`);
|
||||
|
||||
return pterodactyl.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "credits") {
|
||||
logger?.verbose(`Executing credits subcommand`);
|
||||
|
||||
return credits.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "points") {
|
||||
logger?.verbose(`Executing points subcommand`);
|
||||
|
||||
return points.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "welcome") {
|
||||
logger?.verbose(`Executing welcome subcommand`);
|
||||
|
||||
return welcome.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "audits") {
|
||||
logger?.verbose(`Executing audit subcommand`);
|
||||
|
||||
return audits.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "shop") {
|
||||
logger?.verbose(`Executing shop subcommand`);
|
||||
|
||||
return shop.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`No subcommand found`);
|
||||
},
|
||||
};
|
|
@ -3,20 +3,20 @@ import { SlashCommandBuilder } from "@discordjs/builders";
|
|||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Groups
|
||||
import guildGroup from "./guild";
|
||||
import userGroup from "./user";
|
||||
import groups from "./groups";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
metadata: { author: "Zyner" },
|
||||
groups,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("settings")
|
||||
.setDescription("Manage settings.")
|
||||
.addSubcommandGroup(guildGroup.data)
|
||||
.addSubcommandGroup(userGroup.data),
|
||||
|
||||
.addSubcommandGroup(groups.guild.data),
|
||||
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
@ -24,13 +24,7 @@ export default {
|
|||
if (options.getSubcommandGroup() === "guild") {
|
||||
logger.verbose(`Executing guild subcommand`);
|
||||
|
||||
return guildGroup.execute(interaction);
|
||||
}
|
||||
|
||||
if (options.getSubcommandGroup() === "user") {
|
||||
logger.verbose(`Executing user subcommand`);
|
||||
|
||||
return userGroup.execute(interaction);
|
||||
return groups.guild.execute(interaction);
|
||||
}
|
||||
|
||||
logger.verbose(`No subcommand group found`);
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
// Dependencies
|
||||
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
||||
// Modules
|
||||
import appearance from "./modules/appearance";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
data: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("user")
|
||||
.setDescription("User settings.")
|
||||
.addSubcommand((command) =>
|
||||
command
|
||||
.setName("appearance")
|
||||
.setDescription("User appearance settings.")
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("language")
|
||||
.setDescription("Set the language.")
|
||||
.addChoice("English", "en")
|
||||
.addChoice("Swedish", "sv")
|
||||
)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommand() === "appearance") {
|
||||
logger?.verbose(`Executing appearance subcommand`);
|
||||
|
||||
await appearance(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`No subcommand found`);
|
||||
},
|
||||
};
|
|
@ -1,61 +0,0 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
||||
// Models
|
||||
import fetchUser from "@helpers/fetchUser";
|
||||
|
||||
// Function
|
||||
export default async (interaction: CommandInteraction) => {
|
||||
// Destructure member
|
||||
const { options, user, guild } = interaction;
|
||||
|
||||
// Get options
|
||||
const language = options?.getString("language");
|
||||
|
||||
if (guild === null) {
|
||||
return logger?.verbose(`Guild is null`);
|
||||
}
|
||||
|
||||
// Get user object
|
||||
const userDB = await fetchUser(user, guild);
|
||||
|
||||
if (userDB === null) {
|
||||
return logger?.verbose(`User is null`);
|
||||
}
|
||||
|
||||
// Modify values
|
||||
userDB.language = language !== null ? language : userDB?.language;
|
||||
|
||||
// Save guild
|
||||
await userDB?.save()?.then(async () => {
|
||||
logger?.verbose(`Updated user language.`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
{
|
||||
title: ":hammer: Settings - User [Appearance]",
|
||||
description: "Successfully updated user settings.",
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: "🏳️🌈 Language",
|
||||
value: `${userDB?.language}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
};
|
3
src/plugins/shop/groups/index.ts
Normal file
3
src/plugins/shop/groups/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import roles from "./roles";
|
||||
|
||||
export default { roles };
|
|
@ -3,24 +3,25 @@ import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
|
|||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Handlers
|
||||
import logger from "../../../logger";
|
||||
import logger from "@logger";
|
||||
|
||||
import { errorColor, footerText, footerIcon } from "@config/embed";
|
||||
|
||||
// Modules
|
||||
import buy from "./modules/buy";
|
||||
import cancel from "./modules/cancel";
|
||||
import modules from "./modules";
|
||||
|
||||
import guildSchema from "@schemas/guild";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
modules,
|
||||
|
||||
data: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("roles")
|
||||
.setDescription("Shop for custom roles.")
|
||||
.addSubcommand(buy.data)
|
||||
.addSubcommand(cancel.data);
|
||||
.addSubcommand(modules.buy.data)
|
||||
.addSubcommand(modules.cancel.data);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options, guild } = interaction;
|
||||
|
@ -53,13 +54,13 @@ export default {
|
|||
if (options?.getSubcommand() === "buy") {
|
||||
logger.verbose(`Executing buy subcommand`);
|
||||
|
||||
await buy.execute(interaction);
|
||||
await modules.buy.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "cancel") {
|
||||
logger.verbose(`Executing cancel subcommand`);
|
||||
|
||||
await cancel.execute(interaction);
|
||||
await modules.cancel.execute(interaction);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -25,6 +25,8 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: true },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("buy")
|
||||
|
@ -33,11 +35,13 @@ export default {
|
|||
option
|
||||
.setName("name")
|
||||
.setDescription("Name of the role you wish to buy.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("color")
|
||||
.setDescription("Color of the role you wish to buy.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
|
@ -20,12 +20,17 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: true },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("cancel")
|
||||
.setDescription("Cancel a purchase.")
|
||||
.addRoleOption((option) =>
|
||||
option.setName("role").setDescription("Role you wish to cancel.")
|
||||
option
|
||||
.setName("role")
|
||||
.setDescription("Role you wish to cancel.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
7
src/plugins/shop/groups/roles/modules/index.ts
Normal file
7
src/plugins/shop/groups/roles/modules/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import buy from "./buy";
|
||||
import cancel from "./cancel";
|
||||
|
||||
export default {
|
||||
buy,
|
||||
cancel,
|
||||
};
|
|
@ -3,35 +3,37 @@ import { SlashCommandBuilder } from "@discordjs/builders";
|
|||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import pterodactyl from "./modules/pterodactyl";
|
||||
import modules from "./modules";
|
||||
|
||||
// Groups
|
||||
import roles from "./roles";
|
||||
import groups from "./groups";
|
||||
|
||||
// Handlers
|
||||
import logger from "../../logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
metadata: { author: "Zyner" },
|
||||
modules,
|
||||
groups,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("shop")
|
||||
.setDescription("Shop for credits and custom roles.")
|
||||
.addSubcommand(pterodactyl.data)
|
||||
.addSubcommandGroup(roles.data),
|
||||
.addSubcommand(modules.pterodactyl.data)
|
||||
.addSubcommandGroup(groups.roles.data),
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommand() === "pterodactyl") {
|
||||
logger.verbose(`Executing pterodactyl subcommand`);
|
||||
|
||||
return pterodactyl.execute(interaction);
|
||||
return modules.pterodactyl.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommandGroup() === "roles") {
|
||||
logger?.verbose(`Subcommand group is roles`);
|
||||
|
||||
return roles.execute(interaction);
|
||||
return groups.roles.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`No subcommand found.`);
|
||||
|
|
3
src/plugins/shop/modules/index.ts
Normal file
3
src/plugins/shop/modules/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import pterodactyl from "@plugins/shop/modules/pterodactyl";
|
||||
|
||||
export default { pterodactyl };
|
|
@ -1,9 +1,7 @@
|
|||
// Dependencies
|
||||
import { CommandInteraction } from "discord.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import axios from "axios";
|
||||
|
||||
// Configurations
|
||||
import {
|
||||
successColor,
|
||||
errorColor,
|
||||
|
@ -11,20 +9,18 @@ import {
|
|||
footerIcon,
|
||||
} from "@config/embed";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
import encryption from "@handlers/encryption";
|
||||
|
||||
// Helpers
|
||||
import pluralize from "@helpers/pluralize";
|
||||
|
||||
// Models
|
||||
import apiSchema from "@schemas/api";
|
||||
import fetchUser from "@helpers/fetchUser";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
meta: { guildOnly: true, ephemeral: true },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("pterodactyl")
|
||||
|
@ -38,10 +34,8 @@ export default {
|
|||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options, guild, user, client } = interaction;
|
||||
|
||||
// Get options
|
||||
const optionAmount = options?.getInteger("amount");
|
||||
|
||||
// If amount is null
|
||||
if (optionAmount === null) {
|
||||
logger?.verbose(`Amount is null.`);
|
||||
|
||||
|
@ -65,17 +59,14 @@ export default {
|
|||
return logger?.verbose(`Guild is null`);
|
||||
}
|
||||
|
||||
// Get user object
|
||||
const userDB = await fetchUser(user, guild);
|
||||
|
||||
if (userDB === null) {
|
||||
return logger?.verbose(`User is null`);
|
||||
}
|
||||
|
||||
// Get DM user object
|
||||
const dmUser = client?.users?.cache?.get(user?.id);
|
||||
|
||||
// Stop if amount or user credits is below 100
|
||||
if ((optionAmount || userDB?.credits) < 100) {
|
||||
logger?.verbose(`Amount or user credits is below 100.`);
|
||||
|
||||
|
@ -101,7 +92,6 @@ export default {
|
|||
});
|
||||
}
|
||||
|
||||
// Stop if amount or user credits is above 1.000.000
|
||||
if ((optionAmount || userDB?.credits) > 1000000) {
|
||||
logger?.verbose(`Amount or user credits is above 1.000.000.`);
|
||||
|
||||
|
@ -128,7 +118,6 @@ export default {
|
|||
});
|
||||
}
|
||||
|
||||
// Stop if user credits is below amount
|
||||
if (userDB?.credits < optionAmount) {
|
||||
logger?.verbose(`User credits is below amount.`);
|
||||
|
||||
|
@ -154,15 +143,12 @@ export default {
|
|||
});
|
||||
}
|
||||
|
||||
// Generate a unique voucher for the user
|
||||
const code = uuidv4();
|
||||
|
||||
// Get api object
|
||||
const apiCredentials = await apiSchema?.findOne({
|
||||
guildId: guild?.id,
|
||||
});
|
||||
|
||||
// Create a api instance
|
||||
const api = axios?.create({
|
||||
baseURL: apiCredentials?.url,
|
||||
headers: {
|
||||
|
@ -170,13 +156,10 @@ export default {
|
|||
},
|
||||
});
|
||||
|
||||
// Get shop URL
|
||||
const shopUrl = apiCredentials?.url?.replace("/api", "/store");
|
||||
|
||||
// Make API request
|
||||
await api
|
||||
|
||||
// Make a post request to the API
|
||||
?.post("vouchers", {
|
||||
uses: 1,
|
||||
code,
|
||||
|
@ -184,17 +167,14 @@ export default {
|
|||
memo: `${interaction?.createdTimestamp} - ${interaction?.user?.id}`,
|
||||
})
|
||||
|
||||
// If successful
|
||||
?.then(async () => {
|
||||
logger?.verbose(`Successfully created voucher.`);
|
||||
|
||||
// Withdraw amount from user credits
|
||||
userDB.credits -= optionAmount || userDB?.credits;
|
||||
|
||||
// Save new credits
|
||||
await userDB
|
||||
?.save()
|
||||
// If successful
|
||||
|
||||
?.then(async () => {
|
||||
logger?.verbose(`Successfully saved new credits.`);
|
||||
|
||||
|
@ -237,7 +217,6 @@ export default {
|
|||
});
|
||||
})
|
||||
|
||||
// If error occurs
|
||||
.catch(async (error) => {
|
||||
logger?.verbose(`Error saving new credits. - ${error}`);
|
||||
|
||||
|
@ -258,7 +237,6 @@ export default {
|
|||
});
|
||||
})
|
||||
|
||||
// If error occurs
|
||||
.catch(async (error: any) => {
|
||||
logger?.verbose(`Error creating voucher. - ${error}`);
|
||||
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
// Dependencies
|
||||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import lookup from "./modules/lookup";
|
||||
import about from "./modules/about";
|
||||
import stats from "./modules/stats";
|
||||
|
||||
// Handlers
|
||||
import logger from "../../logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
metadata: { author: "Zyner" },
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("utilities")
|
||||
.setDescription("Common utilities.")
|
||||
.addSubcommand(lookup.data)
|
||||
.addSubcommand(about.data)
|
||||
.addSubcommand(stats.data),
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options?.getSubcommand() === "lookup") {
|
||||
logger.verbose(`Executing lookup subcommand`);
|
||||
|
||||
return lookup.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "about") {
|
||||
logger.verbose(`Executing about subcommand`);
|
||||
|
||||
return about.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "stats") {
|
||||
logger.verbose(`Executing stats subcommand`);
|
||||
|
||||
return stats.execute(interaction);
|
||||
}
|
||||
|
||||
logger.verbose(`No subcommand found.`);
|
||||
},
|
||||
};
|
|
@ -1,134 +0,0 @@
|
|||
// Dependencies
|
||||
import axios from "axios";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Configurations
|
||||
import {
|
||||
successColor,
|
||||
errorColor,
|
||||
footerText,
|
||||
footerIcon,
|
||||
} from "@config/embed";
|
||||
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
|
||||
// Handlers
|
||||
import logger from "@logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("lookup")
|
||||
.setDescription(
|
||||
"Lookup a domain or ip. (Request sent over HTTP, proceed with caution!)"
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("query")
|
||||
.setDescription("The query you want to look up.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { options } = interaction;
|
||||
// Get lookup query
|
||||
const query = options?.getString("query");
|
||||
|
||||
// Make API request
|
||||
await axios
|
||||
// Make a get request
|
||||
?.get(`http://ip-api.com/json/${query}`)
|
||||
|
||||
// If successful
|
||||
?.then(async (res) => {
|
||||
// If query failed
|
||||
if (res?.data?.status === "fail") {
|
||||
// Create embed object
|
||||
const embed = {
|
||||
title: ":hammer: Utilities - Lookup",
|
||||
description: `${res?.data?.message}: ${res?.data?.query}`,
|
||||
color: errorColor,
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
},
|
||||
};
|
||||
|
||||
// Send interaction reply
|
||||
await interaction?.editReply({ embeds: [embed] });
|
||||
}
|
||||
|
||||
// If query is successful
|
||||
else if (res?.data?.status === "success") {
|
||||
// Create embed object
|
||||
const embed = {
|
||||
title: ":hammer: Utilities - Lookup",
|
||||
fields: [
|
||||
{
|
||||
name: "AS",
|
||||
value: `${res?.data?.as || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "Country",
|
||||
value: `${res?.data?.country || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "Country Code",
|
||||
value: `${res?.data?.countryCode || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "Region",
|
||||
value: `${res?.data?.region || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "Region Name",
|
||||
value: `${res?.data?.regionName || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "City",
|
||||
value: `${res?.data?.city || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "ZIP Code",
|
||||
value: `${res?.data?.zip || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "Latitude",
|
||||
value: `${res?.data?.lat || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "Longitude",
|
||||
value: `${res?.data?.lon || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "Timezone",
|
||||
value: `${res?.data?.timezone || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "ISP",
|
||||
value: `${res?.data?.isp || "Not available"}`,
|
||||
},
|
||||
{
|
||||
name: "Organization",
|
||||
value: `${res?.data?.org || "Not available"}`,
|
||||
},
|
||||
],
|
||||
color: successColor,
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
},
|
||||
};
|
||||
|
||||
// Send interaction reply
|
||||
await interaction?.editReply({ embeds: [embed] });
|
||||
}
|
||||
})
|
||||
.catch(async (e) => {
|
||||
logger?.error(e);
|
||||
});
|
||||
},
|
||||
};
|
40
src/plugins/utility/index.ts
Normal file
40
src/plugins/utility/index.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Dependencies
|
||||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import modules from "@plugins/utility/modules";
|
||||
|
||||
// Handlers
|
||||
import logger from "../../logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
modules,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("utility")
|
||||
.setDescription("Common utility.")
|
||||
|
||||
.addSubcommand(modules.lookup.data)
|
||||
.addSubcommand(modules.about.data)
|
||||
.addSubcommand(modules.stats.data)
|
||||
.addSubcommand(modules.avatar.data),
|
||||
|
||||
async execute(interaction: CommandInteraction) {
|
||||
const { options } = interaction;
|
||||
|
||||
switch (options.getSubcommand()) {
|
||||
case "lookup":
|
||||
return modules.lookup.execute(interaction);
|
||||
case "about":
|
||||
return modules.about.execute(interaction);
|
||||
case "stats":
|
||||
return modules.stats.execute(interaction);
|
||||
case "avatar":
|
||||
return modules.avatar.execute(interaction);
|
||||
default:
|
||||
logger.error(`Unknown subcommand ${options.getSubcommand()}`);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -9,6 +9,8 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
|||
|
||||
// Function
|
||||
export default {
|
||||
meta: { guildOnly: false, ephemeral: false },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command.setName("about").setDescription("About this bot!)");
|
||||
},
|
52
src/plugins/utility/modules/avatar.ts
Normal file
52
src/plugins/utility/modules/avatar.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { successColor, footerText, footerIcon } from "@config/embed";
|
||||
|
||||
import i18next from "i18next";
|
||||
import { CommandInteraction, MessageEmbed } from "discord.js";
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
|
||||
export default {
|
||||
meta: { guildOnly: false, ephemeral: false },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("avatar")
|
||||
.setDescription("Check someones avatar!)")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user whose avatar you want to check")
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const { locale } = interaction;
|
||||
|
||||
const userOption = interaction.options.getUser("user");
|
||||
|
||||
const targetUser = userOption || interaction.user;
|
||||
|
||||
const embed = new MessageEmbed()
|
||||
.setTitle(
|
||||
i18next.t("utility:modules:avatar:general:title", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
})
|
||||
)
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
embed
|
||||
.setDescription(
|
||||
i18next.t("utility:modules:avatar:success01:description", {
|
||||
lng: locale,
|
||||
ns: "plugins",
|
||||
user: targetUser,
|
||||
})
|
||||
)
|
||||
.setThumbnail(targetUser.displayAvatarURL())
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
11
src/plugins/utility/modules/index.ts
Normal file
11
src/plugins/utility/modules/index.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import avatar from "@plugins/utility/modules/avatar";
|
||||
import about from "@plugins/utility/modules/about";
|
||||
import lookup from "@plugins/utility/modules/lookup";
|
||||
import stats from "@plugins/utility/modules/stats";
|
||||
|
||||
export default {
|
||||
avatar,
|
||||
about,
|
||||
lookup,
|
||||
stats,
|
||||
};
|
118
src/plugins/utility/modules/lookup.ts
Normal file
118
src/plugins/utility/modules/lookup.ts
Normal file
|
@ -0,0 +1,118 @@
|
|||
import axios from "axios";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
import { successColor, errorColor } from "@config/embed";
|
||||
|
||||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
|
||||
import embedBuilder from "@root/helpers/embedBuilder";
|
||||
|
||||
export default {
|
||||
meta: { guildOnly: false, ephemeral: false },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("lookup")
|
||||
.setDescription(
|
||||
"Lookup a domain or ip. (Request sent over HTTP, proceed with caution!)"
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("query")
|
||||
.setDescription("The query you want to look up.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
const embedTitle = "[:hammer:] Utility (Lookup)";
|
||||
|
||||
embedBuilder.setTitle(embedTitle);
|
||||
|
||||
const { options } = interaction;
|
||||
const query = options.getString("query");
|
||||
|
||||
await axios
|
||||
.get(`http://ip-api.com/json/${query}`)
|
||||
.then(async (response) => {
|
||||
if (response.data.status !== "success") {
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
embedBuilder
|
||||
.setColor(errorColor)
|
||||
.setDescription(
|
||||
`${response?.data?.message}: ${response?.data?.query}`
|
||||
),
|
||||
],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
embedBuilder.setColor(successColor).setFields([
|
||||
{
|
||||
name: ":classical_building: AS",
|
||||
value: `${response.data.as || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":classical_building: ISP",
|
||||
value: `${response.data.isp || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":classical_building: Organization",
|
||||
value: `${response.data.org || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":compass: Latitude",
|
||||
value: `${response.data.lat || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":compass: Longitude",
|
||||
value: `${response.data.lon || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":clock4: Timezone",
|
||||
value: `${response.data.timezone || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Country",
|
||||
value: `${response.data.country || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Region",
|
||||
value: `${response.data.regionName || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: City",
|
||||
value: `${response.data.city || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Country Code",
|
||||
value: `${response.data.countryCode || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Region Code",
|
||||
value: `${response.data.region || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: ZIP",
|
||||
value: `${response.data.zip || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
]),
|
||||
],
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
|
@ -2,6 +2,8 @@ import { successColor, footerText, footerIcon } from "@config/embed";
|
|||
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
|
||||
import { CommandInteraction } from "discord.js";
|
||||
export default {
|
||||
meta: { guildOnly: false, ephemeral: false },
|
||||
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command.setName("stats").setDescription("Check bot statistics!)");
|
||||
},
|
|
@ -55,13 +55,25 @@ export default async (client: Client) => {
|
|||
|
||||
const rRole = rMember.roles.cache.get(roleId);
|
||||
|
||||
if (!rRole) {
|
||||
logger.error(`Role ${roleId} not found for shop role ${roleId}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rMember) {
|
||||
if (!rMember || !rRole) {
|
||||
logger.error(`Member ${userId} not found for shop role ${roleId}.`);
|
||||
await shopRoleSchema
|
||||
.deleteOne({
|
||||
userId,
|
||||
roleId,
|
||||
guildId,
|
||||
})
|
||||
.then(async () => {
|
||||
logger.verbose(
|
||||
`Shop role document ${roleId} has been deleted from user ${userId}.`
|
||||
);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger.error(
|
||||
`Error deleting shop role document ${roleId} from user ${userId}.`,
|
||||
error
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -79,23 +91,6 @@ export default async (client: Client) => {
|
|||
|
||||
if (!rMember) {
|
||||
logger.error(`Member ${userId} not found for shop role ${roleId}.`);
|
||||
await shopRoleSchema
|
||||
.deleteOne({
|
||||
userId,
|
||||
roleId,
|
||||
guildId,
|
||||
})
|
||||
.then(async () => {
|
||||
logger.verbose(
|
||||
`Shop role document ${roleId} has been deleted from user ${userId}.`
|
||||
);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger.error(
|
||||
`Error deleting shop role document ${roleId} from user ${userId}.`,
|
||||
error
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"moduleResolution": "node",
|
||||
"isolatedModules": true,
|
||||
"outDir": "./build",
|
||||
"resolveJsonModule": true,
|
||||
"baseUrl": "./src",
|
||||
"typeRoots": ["/types/common", "./node_modules/@types"],
|
||||
"paths": {
|
||||
|
|
Loading…
Add table
Reference in a new issue