diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..4988fcde3
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,9 @@
+.DS_Store
+node_modules/
+.git/
+.vscode/
+docs/
+*.log
+*.tar.gz
+*.tar
+.env
\ No newline at end of file
diff --git a/.env.example b/.env.example
index 4b417395c..7fbf4f575 100644
--- a/.env.example
+++ b/.env.example
@@ -1,20 +1,24 @@
-# Bot Token [Required]
-BOT_TOKEN=
-
-# Mongo Database Connection String [Required]
-MONGO_CONNECTION=
-
-# Webhooks [Optional]
-ERROR_LOGS=
-JOIN_LEAVE_LOGS=
-
-# Dashboard [Required for dashboard]
-BOT_SECRET=
-SESSION_PASSWORD=
-
-# API Keys [Required for Weather Command]
-WEATHERSTACK_KEY=
-
-# SPOTFIY [Required for Spotify Support]
-SPOTIFY_CLIENT_ID=
-SPOTIFY_CLIENT_SECRET=
+@@ -1,23 +0,0 @@
+# Bot Token [Required]
+BOT_TOKEN=
+
+# Mongo Database Connection String [Required]
+MONGO_CONNECTION=
+
+# Webhooks [Optional]
+ERROR_LOGS=
+JOIN_LEAVE_LOGS=
+
+# Dashboard [Required for dashboard]
+BOT_SECRET=
+SESSION_PASSWORD=
+
+# Required for Weather Command (https://weatherstack.com)
+WEATHERSTACK_KEY=
+
+# Required for image commands (https://strangeapi.fun/docs)
+STRANGE_API_KEY=
+
+# SPOTFIY [Required for Spotify Support]
+SPOTIFY_CLIENT_ID=
+SPOTIFY_CLIENT_SECRET=
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
index d25f7aee2..6e037488c 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -13,8 +13,5 @@
"no-unused-vars": ["error", { "args": "none" }],
"jsdoc/no-undefined-types": 1,
"no-cond-assign": 0
- },
- "globals": {
- "__appRoot": "readonly"
}
}
diff --git a/.gitbook.yaml b/.gitbook.yaml
index 57e123cae..e66b6e80f 100644
--- a/.gitbook.yaml
+++ b/.gitbook.yaml
@@ -1,4 +1,4 @@
root: ./docs/
structure:
readme: ../README.md
- summary: SUMMARY.md
+ summary: SUMMARY.md
diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
new file mode 100644
index 000000000..9a79ead56
--- /dev/null
+++ b/.github/workflows/docker-publish.yml
@@ -0,0 +1,48 @@
+name: Publish Docker image
+
+on:
+ push:
+ branches: [main]
+
+env:
+ REGISTRY: docker.io
+ IMAGE_NAME: saitejamadha/discord-js-bot
+
+jobs:
+ push_to_registry:
+ name: Push Docker image to Docker Hub
+ runs-on: ubuntu-latest
+ permissions:
+ packages: write
+ contents: read
+ attestations: write
+ id-token: write
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v4
+
+ - name: Log in to Docker Hub
+ uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
+ with:
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ - name: Extract version from package.json
+ id: version
+ run: echo "VERSION=$(jq -r .version package.json)" >> $GITHUB_ENV
+
+ - name: Build and push Docker image
+ id: push
+ uses: docker/build-push-action@v4
+ with:
+ context: .
+ file: ./Dockerfile
+ push: true
+ tags: ${{ env.IMAGE_NAME }}:${{ env.VERSION }}
+
+ - name: Generate artifact attestation
+ uses: actions/attest-build-provenance@v1
+ with:
+ subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
+ subject-digest: ${{ steps.push.outputs.digest }}
+ push-to-registry: false
diff --git a/.gitignore b/.gitignore
index de6c79883..7d0b3e132 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
+.DS_Store
.vscode/
node_modules/
-logs/*
+*.log
+*.tar.gz
.env
\ No newline at end of file
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 000000000..c37466e2b
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npx lint-staged
\ No newline at end of file
diff --git a/.prettierrc.json b/.prettierrc.json
index 45a0c08e5..e1f258c61 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -6,5 +6,7 @@
"singleQuote": false,
"printWidth": 120,
"bracketSpacing": true,
- "arrowParens": "always"
+ "arrowParens": "always",
+ "endOfLine": "lf"
}
+
diff --git a/.replit b/.replit
index 2efe7969f..7c8aef1c6 100644
--- a/.replit
+++ b/.replit
@@ -1,2 +1,89 @@
+entrypoint = "bot.js"
+
+hidden = [".config", "package-lock.json"]
+
+[interpreter]
+command = [
+ "prybar-nodejs",
+ "-q",
+ "--ps1",
+ "\u0001\u001b[33m\u0002\u0001\u001b[00m\u0002 ",
+ "-i"
+]
+
+[[hints]]
+regex = "Error \\[ERR_REQUIRE_ESM\\]"
+message = "We see that you are using require(...) inside your code. We currently do not support this syntax. Please use 'import' instead when using external modules. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)"
+
+[nix]
+channel = "stable-22_11"
+
+[env]
+XDG_CONFIG_HOME = "/home/runner/$REPL_SLUG/.config"
+PATH = "/home/runner/$REPL_SLUG/.config/npm/node_global/bin:/home/runner/$REPL_SLUG/node_modules/.bin"
+npm_config_prefix = "/home/runner/$REPL_SLUG/.config/npm/node_global"
+
+[gitHubImport]
+requiredFiles = [".replit", "replit.nix", ".config", "package.json", "package-lock.json"]
+
+[packager]
language = "nodejs"
-run = "node_modules/.bin/node bot.js"
\ No newline at end of file
+
+ [packager.features]
+ packageSearch = true
+ guessImports = true
+ enabledForHosting = false
+
+[unitTest]
+language = "nodejs"
+
+[debugger]
+support = true
+
+ [debugger.interactive]
+ transport = "localhost:0"
+ startCommand = [ "dap-node" ]
+
+ [debugger.interactive.initializeMessage]
+ command = "initialize"
+ type = "request"
+
+ [debugger.interactive.initializeMessage.arguments]
+ clientID = "replit"
+ clientName = "replit.com"
+ columnsStartAt1 = true
+ linesStartAt1 = true
+ locale = "en-us"
+ pathFormat = "path"
+ supportsInvalidatedEvent = true
+ supportsProgressReporting = true
+ supportsRunInTerminalRequest = true
+ supportsVariablePaging = true
+ supportsVariableType = true
+
+ [debugger.interactive.launchMessage]
+ command = "launch"
+ type = "request"
+
+ [debugger.interactive.launchMessage.arguments]
+ args = []
+ console = "externalTerminal"
+ cwd = "."
+ environment = []
+ pauseForSourceMap = false
+ program = "./index.js"
+ request = "launch"
+ sourceMaps = true
+ stopOnEntry = false
+ type = "pwa-node"
+
+[languages]
+
+[languages.javascript]
+pattern = "**/{*.js,*.jsx,*.ts,*.tsx}"
+
+[languages.javascript.languageServer]
+start = "typescript-language-server --stdio"
+
+[deployment]
+run = ["sh", "-c", "node index.js"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..261eeb9e9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Procfile b/Procfile
new file mode 100644
index 000000000..e8f79ea7b
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: npm start
\ No newline at end of file
diff --git a/README.md b/README.md
index 1b66a5cfb..705639beb 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,45 @@
-# 🤖 About Me
+
+
+
+
+ Discord.js v14 Bot
+
+
-![Strange Bot](https://i.imgur.com/nFrS5wC.png)
+Admin, AutoMod, Anime, Economy, Fun, Giveaway, Image, Invite, Information, Moderation, Music, Owner, Social, Statistics, Suggestion, Ticket, Utility and More...
-> An awesome multipurpose discord bot built using [discord.js v13](https://discord.js.org) with support for slash commands and context menus
+
-> Demo Bot: [Invite Here](https://discord.com/oauth2/authorize?client\_id=752922609733337190\&permissions=397602323830\&scope=bot%20applications.commands)
->
-> Support Server: [Join Here](https://discord.gg/fE75UShbqB)
->
-> Documentation URL: [Visit Here](https://docs.strangebot.xyz)
+
+ Resource Links
+ •
+ Prerequisites
+ •
+ Getting Started
+ •
+ Features
+ •
+ Contributing
+
-### Prerequisites
+
-* [Node.js](https://nodejs.org/en/) v16.6.0 or higher
-* [Git](https://git-scm.com/downloads)
-* [MongoDB](https://www.mongodb.com)
+## 🔗 Resource Links
-### Getting Started
+- 🤖 Demo Bot: [Invite Here](https://discord.com/oauth2/authorize?client_id=1013236808353599488&permissions=397602323830&scope=bot%20applications.commands)
+- 🤝 Support Server: [Join Here](https://discord.gg/2gPy75zgbW)
+- 📂 Documentation URL: [Visit Here](https://strangedocs.hostz.me)
+- 🐳 Docker Image: [Hub](https://hub.docker.com/r/saitejamadha/discord-js-bot)
-* Open the terminal and run the following commands
+## 📦 Prerequisites
+
+- [Node.js](https://nodejs.org/en/) v16.11.0 or higher
+- [Git](https://git-scm.com/downloads)
+- [MongoDB](https://www.mongodb.com)
+
+## 🚀 Getting Started
+
+- Open the terminal and run the following commands
```
git clone https://github.com/saiteja-madha/discord-js-bot.git
@@ -26,46 +47,111 @@ cd discord-js-bot
npm install
```
-* Wait for all the dependencies to be installed
-* Rename `.env.example` to `.env` and fill the values
-* Optionally edit `config.js`
-* Type `npm run start` to start the bot
+- Wait for all the dependencies to be installed
+- Rename `.env.example` to `.env` and fill the values
+- Optionally edit `config.js`
+- Type `npm run start` to start the bot
If you need any additional help, make sure to read our guides [here](docs/additional/installation.md)
-### Features
+
+
+ ✨ Features ✨
+
+### 📡 **Advanced Dashboard**
+
+- Manage your servers and make your server-specific settings!
+- Make custom adjustments easy!
+
+### 🛑 **Powerful Moderation:**
+
+- **Moderation Commands.**
_Commands:_ `ban`, `unban`, `timeout`, `voice moderation`, `deafen`, `move`, `warn`, `setnick`, ...
+- **Multi-Function Purge Commands.**
_Commands:_ `purge`, `purge attach`, `purge bots`, `purge links`, `purge token`, `purge user`, ...
+
+### 🤖 **Auto Moderation:**
+
+- **Anti system**
_Commands:_ `anti ghostping`, `anti spam`, `anti massmention`, ...
+- **Auto Delete system**
_Commands:_ `autodelete attachments`, `autodelete invites`, `autodelete links`, `autodelete maxlines`, ...
+- **AutoMod system**
_Commands:_ `automod status`, `automod strikes`, `automod action`, `automod debug`, `automod whitelist`, ...
+
+### ⚙️ **Admin Configuration:**
+
+- **Let a bot be the server's assistant!**
_Commands:_ `autorole`, `farewell`, `welcome`, `counters`, `flag translation`, `reaction roles`, ...
+- **Make custom settings for your own server.**
_Commands:_ `setprefix`, `maxwarns`, `modlog`...
+
+### 💁 **Information Gathering:**
+
+- **User Context Interactions**
+- **Advanced Information** Get deep information about a user, channel, role, etc.
+
+### 🎵 **Music:**
+
+- **LossLess Music!** Enjoy high quality lossless music
+- **Multi-Platform** Play music from YouTube, SoundCloud, Spotify, and more
+- **Filters** Apply filters to your music and spice it up
+
+### 🎉 **Giveaways:**
+
+- **Easy to use** Create giveaways with ease
+- **Role specific** giveaways
+- **Customizable** Customize the giveaway to your liking
+- **Limitless** Create unlimited giveaways
+
+### 🫂 **Social Content:**
+
+- **You Have A CV In Each Server-Specific Bot!**
_Commands:_ `rep`, `rep view`...
+- **Do You Love Someone?**
_Commands:_ `rep give`...
+
+### 🎟 **Ticket System:**
+
+- **Make Supporting Members A Breeze With Tickets!**
Highly customizable ticket system with staff roles
+- **Multiple Categories**
Don't Want The Tickets To Be Everywhere? Categorize them using select menus
+
+### 📉 **Stats Tracking:**
+
+- **Levelling** Track your server's activity with a level system
+- **Leaderboards** See who is the most active user in your server
+- **Customizable System** Configure the levelup message, rank cards to your liking
+
+### 🙋♂️ **Suggestions:**
+
+- **Get Suggestions From Server Members To Help Your Server Become The Best!**
_Commands:_ `suggest`, `suggestion`...
+- **Accept Or Decline The Suggestions And Customize Them To The Max!**
_Commands:_ `suggestion status`, `suggestion channel`, `suggestion appch`, `suggestion rejch`, `suggestion approve`, `suggestion staffadd`, `suggestion staffremove`...
+
+### ⚒️ **Utility Commands:**
+
+- **Need Some Help With Something? Use The Utility Commands To Find Out The Answer To It**
_Commands:_ `bigemoji`, `covid`, `pokedex`, `urban`, `weather`, ...
+- **Need Help With Some More Stuff?**
_Commands:_ `help`, `proxies`, `translate`, `paste`, ...
+
+### ⭐ **Anime Content:**
+
+- **Love Anime? Express You Love To Someone Using The React Commands**
_Commands:_ `react`, `hug`, `kiss`, `cuddle`, `pat`, `poke`, `slap`, `smug`, ...
+
+### 🪙 **Economy System:**
+
+- **Want To Become Richest? Use The Economy Commands!**
_Commands:_ `bank`, `daily`, `beg`, `gamble`...
+- **Give People Money, Check Your Balance, Or Just Flex!**
_Commands:_ `bank balance`, `bank deposit`, `bank withdraw`, `bank transfer`, ...
+
+### 😁 **Fun Commands:**
-Strange is a feature-rich discord bot with new features constantly being updated! Current features include
+- **Have Some Fun In Your Server!**
_Commands:_ `animal`, `facts`, `meme`, `flip`, ...
+- **Play Games And Enjoy Yourself**
_Commands:_ `snake`, `together`, `flip coin`, `flip text`, ...
-* **Auto-Moderation**: Power auto-moderation to keep your discord server clean
-* **Powerful Moderation with Logging**: Moderate and log every action you take
-* **Image Manipulation**: Have fun with various image `filters` and `generators`
-* **Economy & XP System**: Engage user interaction with the economy and Levelling system
-* **Invite Tracking**: Best invite tracking with configurable invite ranks
-* **Ticketing**: Support for creating multiple `ticket` channels
-* **Reaction Roles**: Support for creation of multiple custom reaction roles
-* **Greeting**: Highly Customizable welcome and farewell embeds
+### 📨 **Invite Tracking:**
-### Categories
+- **Track who has been inviting people to your server!**
+- **Invite Ranks!** Inviter can get awesome rewards and be recognised
+- **Configure these settings and customize them to your liking!**
_Commands:_ `resetinvites`, `addinvites`, `invitesimport`, `inviterank`...
-Strange has an extensive list of all useful commands (**more than 100**) which are categorized as follows
+### 📷 **Image Manipulation:**
-* **Automod**: `antighostping`, `antiinvites`, `antilinks`, `antiscam`, `maxlines`, `maxmentions`, ...
-* **Admin**: `welcome`, `farewell`, `reaction-roles`, ...
-* **Economy**: `daily`, `gamble`, `deposit`, `withdraw`, `transfer`, ...
-* **Fun**: `cat`, `doc`, `flipcoin`, `fliptext`, ...
-* **Information**: `avatar`, `roleinfo`, `channelinfo`, `guildinfo`, `profile`, ...
-* **Invites**: `inviter`, `invites`, `invitesimport`, `invitecodes`, ...
-* **Moderation**: `warn`, `kick`, `softban`, `ban`, `mute`, `unmute`, ...
-* **Music**: `play`, `pause`, `resume`, `stop`, `skip`, `queue`, `np`, ...
-* **Social**: `reputation list,` `give reputation,` ...
-* **Ticket**: setup, close, log, ...
-* **Utility**: `proxies`, `translation`, `weather`, `covid`, ...
+- **Customize other peoples avatars**
_Commands:_ `blur`, `greyscale`, `invert`, `pixelate`, `blur`, `sepia`, `sharpen`, `ad`, `affect`, `beautiful`, `color`...
+- **Make some images by yourself or make some art**
_Commands:_ `bobross`, `confusedstonk`, `delete`, `facepalm`, ` hitler`, `jail`, `jokeoverhead`, `karaba`, `mms`, `notstonk`, `poutine`, `rainbow`, `rip`, ` shit`, `stonk`, `tatoo`, `thomas`, `trash`, `wanted`, `wasted`, ...
-A complete list of commands can be found in the [documentation](docs/commands/)
+
-### 🤝 Contributing
+ 🤝 Contributing 🤝
-* Special thanks to [@Androzz](https://github.com/Androz2091/AtlantaBot) for the [dashboard](https://github.com/Androz2091/AtlantaBot) and his other cool discord bot projects
-* Feel free to [Fork](https://github.com/saiteja-madha/discord-js-bot/fork) this repository, create a feature branch and submit a pull request
-* You can check all the planned features [here](https://github.com/saiteja-madha/discord-js-bot/projects) or make a request for one at our discord
+- Special thanks to [@Androzz](https://github.com/Androz2091/AtlantaBot) for the [dashboard](https://github.com/Androz2091/AtlantaBot) and his other cool discord bot projects
+- Feel free to [Fork](https://github.com/saiteja-madha/discord-js-bot/fork) this repository, create a feature branch and submit a pull request
+- You can keep track of all the planned features [here](https://github.com/saiteja-madha/discord-js-bot/projects) or make a request for one at our discord
diff --git a/bot.js b/bot.js
index 39f1ed1a6..799a7855a 100644
--- a/bot.js
+++ b/bot.js
@@ -1,13 +1,17 @@
require("dotenv").config();
require("module-alias/register");
-require("@src/helpers/extenders");
-const path = require("path");
-const { validateConfig, checkForUpdates } = require("@utils/botUtils");
+// register extenders
+require("@helpers/extenders/Message");
+require("@helpers/extenders/Guild");
+require("@helpers/extenders/GuildChannel");
+
+const { checkForUpdates } = require("@helpers/BotUtils");
const { initializeMongoose } = require("@src/database/mongoose");
const { BotClient } = require("@src/structures");
+const { validateConfiguration } = require("@helpers/Validator");
-global.__appRoot = path.resolve(__dirname);
+validateConfiguration();
// initialize client
const client = new BotClient();
@@ -19,11 +23,6 @@ client.loadEvents("src/events");
process.on("unhandledRejection", (err) => client.logger.error(`Unhandled exception`, err));
(async () => {
- validateConfig();
-
- // initialize the database
- await initializeMongoose();
-
// check for updates
await checkForUpdates();
@@ -32,10 +31,15 @@ process.on("unhandledRejection", (err) => client.logger.error(`Unhandled excepti
client.logger.log("Launching dashboard");
try {
const { launch } = require("@root/dashboard/app");
+
+ // let the dashboard initialize the database
await launch(client);
} catch (ex) {
client.logger.error("Failed to launch dashboard", ex);
}
+ } else {
+ // initialize the database
+ await initializeMongoose();
}
// start the client
diff --git a/config.js b/config.js
index b851056d0..33db48fed 100644
--- a/config.js
+++ b/config.js
@@ -1,103 +1,134 @@
module.exports = {
- OWNER_IDS: [], // Bot owner ID's
- PREFIX: "!", // Default prefix for the bot
+ OWNER_IDS: [""], // Bot owner ID's
SUPPORT_SERVER: "", // Your bot support server
- PRESENCE: {
- ENABLED: true, // Whether or not the bot should update its status
- STATUS: "online", // The bot's status [online, idle, dnd, invisible]
- TYPE: "WATCHING", // Status type for the bot [PLAYING | LISTENING | WATCHING | COMPETING]
- MESSAGE: "{members} members in {servers} servers", // Your bot status message
- },
- DASHBOARD: {
- enabled: false, // enable or disable dashboard
- baseURL: "http://localhost:8080", // base url
- failureURL: "http://localhost:8080", // failure redirect url
- port: "8080", // port to run the bot on
+ PREFIX_COMMANDS: {
+ ENABLED: true, // Enable/Disable prefix commands
+ DEFAULT_PREFIX: "!", // Default prefix for the bot
},
INTERACTIONS: {
SLASH: false, // Should the interactions be enabled
CONTEXT: false, // Should contexts be enabled
GLOBAL: false, // Should the interactions be registered globally
- TEST_GUILD_ID: "xxxxxxxxxx", // Guild ID where the interactions should be registered. [** Test you commands here first **]
+ TEST_GUILD_ID: "xxxxxxxxxxx", // Guild ID where the interactions should be registered. [** Test you commands here first **]
},
- XP_SYSTEM: {
- COOLDOWN: 5, // Cooldown in seconds between messages
- DEFAULT_LVL_UP_MSG: "{m}, You just advanced to **Level {l}**",
+ EMBED_COLORS: {
+ BOT_EMBED: "#068ADD",
+ TRANSPARENT: "#36393F",
+ SUCCESS: "#00A56A",
+ ERROR: "#D61A3C",
+ WARNING: "#F7E919",
},
- MISCELLANEOUS: {
- DAILY_COINS: 100, // coins to be received by daily command
+ CACHE_SIZE: {
+ GUILDS: 100,
+ USERS: 10000,
+ MEMBERS: 10000,
+ },
+ MESSAGES: {
+ API_ERROR: "Unexpected Backend Error! Try again later or contact support server",
+ },
+
+ // PLUGINS
+
+ AUTOMOD: {
+ ENABLED: false,
+ LOG_EMBED: "#36393F",
+ DM_EMBED: "#36393F",
+ },
+
+ DASHBOARD: {
+ enabled: false, // enable or disable dashboard
+ baseURL: "http://localhost:8080", // base url
+ failureURL: "http://localhost:8080", // failure redirect url
+ port: "8080", // port to run the bot on
},
+
ECONOMY: {
+ ENABLED: false,
CURRENCY: "₪",
DAILY_COINS: 100, // coins to be received by daily command
MIN_BEG_AMOUNT: 100, // minimum coins to be received when beg command is used
MAX_BEG_AMOUNT: 2500, // maximum coins to be received when beg command is used
},
- SUGGESTIONS: {
- ENABLED: true, // Should the suggestion system be enabled
- EMOJI: {
- UP_VOTE: "⬆️",
- DOWN_VOTE: "⬇️",
- },
- DEFAULT_EMBED: "#0099ff",
- APPROVED_EMBED: "#00ff00",
- DENIED_EMBED: "#ff0000",
- },
- IMAGE: {
- BASE_API: "https://image-api.strangebot.xyz",
- },
+
MUSIC: {
- IDLE_TIME: 60, // Time in seconds before the bot disconnects from the voice channel
+ ENABLED: false,
+ IDLE_TIME: 60, // Time in seconds before the bot disconnects from an idle voice channel
MAX_SEARCH_RESULTS: 5,
- NODES: [
+ DEFAULT_SOURCE: "SC", // YT = Youtube, YTM = Youtube Music, SC = SoundCloud
+ // Add any number of lavalink nodes here
+ // Refer to https://github.com/freyacodes/Lavalink to host your own lavalink server
+ LAVALINK_NODES: [
{
- host: "ger.lavalink.mitask.tech",
+ host: "localhost",
port: 2333,
- password: "lvserver",
- identifier: "German Link",
- retryDelay: 5000,
- secure: false,
- },
- {
- host: "usa.lavalink.mitask.tech",
- port: 2333,
- password: "lvserver",
- identifier: "USA Link",
- retryDelay: 5000,
+ password: "youshallnotpass",
+ id: "Local Node",
secure: false,
},
],
},
- /* Bot Embed Colors */
- EMBED_COLORS: {
- BOT_EMBED: "#068ADD",
- TRANSPARENT: "#36393F",
- SUCCESS: "#00A56A",
- ERROR: "#D61A3C",
- WARNING: "#F7E919",
- AUTOMOD: "#36393F",
- TICKET_CREATE: "#068ADD",
- TICKET_CLOSE: "#068ADD",
- TIMEOUT_LOG: "#102027",
- UNTIMEOUT_LOG: "#4B636E",
- KICK_LOG: "#FF7961",
- SOFTBAN_LOG: "#AF4448",
- BAN_LOG: "#D32F2F",
- VMUTE_LOG: "#102027",
- VUNMUTE_LOG: "#4B636E",
- DEAFEN_LOG: "#102027",
- UNDEAFEN_LOG: "#4B636E",
- DISCONNECT_LOG: "RANDOM",
- MOVE_LOG: "RANDOM",
- GIVEAWAYS: "#FF468A",
- },
- /* Maximum number of keys that can be stored */
- CACHE_SIZE: {
- GUILDS: 100,
- USERS: 10000,
- MEMBERS: 10000,
+
+ GIVEAWAYS: {
+ ENABLED: false,
+ REACTION: "🎁",
+ START_EMBED: "#FF468A",
+ END_EMBED: "#FF468A",
},
- MESSAGES: {
- API_ERROR: "Unexpected Backend Error! Try again later or contact support server",
+
+ IMAGE: {
+ ENABLED: false,
+ BASE_API: "https://strangeapi.hostz.me/api",
+ },
+
+ INVITE: {
+ ENABLED: false,
+ },
+
+ MODERATION: {
+ ENABLED: false,
+ EMBED_COLORS: {
+ TIMEOUT: "#102027",
+ UNTIMEOUT: "#4B636E",
+ KICK: "#FF7961",
+ SOFTBAN: "#AF4448",
+ BAN: "#D32F2F",
+ UNBAN: "#00C853",
+ VMUTE: "#102027",
+ VUNMUTE: "#4B636E",
+ DEAFEN: "#102027",
+ UNDEAFEN: "#4B636E",
+ DISCONNECT: "RANDOM",
+ MOVE: "RANDOM",
+ },
+ },
+
+ PRESENCE: {
+ ENABLED: false, // Whether or not the bot should update its status
+ STATUS: "online", // The bot's status [online, idle, dnd, invisible]
+ TYPE: "WATCHING", // Status type for the bot [PLAYING | LISTENING | WATCHING | COMPETING]
+ MESSAGE: "{members} members in {servers} servers", // Your bot status message
+ },
+
+ STATS: {
+ ENABLED: false,
+ XP_COOLDOWN: 5, // Cooldown in seconds between messages
+ DEFAULT_LVL_UP_MSG: "{member:tag}, You just advanced to **Level {level}**",
+ },
+
+ SUGGESTIONS: {
+ ENABLED: false, // Should the suggestion system be enabled
+ EMOJI: {
+ UP_VOTE: "⬆️",
+ DOWN_VOTE: "⬇️",
+ },
+ DEFAULT_EMBED: "#4F545C",
+ APPROVED_EMBED: "#43B581",
+ DENIED_EMBED: "#F04747",
+ },
+
+ TICKET: {
+ ENABLED: false,
+ CREATE_EMBED: "#068ADD",
+ CLOSE_EMBED: "#068ADD",
},
};
diff --git a/dashboard/app.js b/dashboard/app.js
index 96995a50c..c980e0f6c 100644
--- a/dashboard/app.js
+++ b/dashboard/app.js
@@ -7,6 +7,8 @@ module.exports.launch = async (client) => {
const express = require("express"),
session = require("express-session"),
+ MongoStore = require("connect-mongo"),
+ mongoose = require("@src/database/mongoose"),
path = require("path"),
app = express();
@@ -19,6 +21,8 @@ module.exports.launch = async (client) => {
client.states = {};
client.config = config;
+ const db = await mongoose.initializeMongoose();
+
/* App configuration */
app
.use(express.json()) // For post methods
@@ -28,7 +32,23 @@ module.exports.launch = async (client) => {
.use(express.static(path.join(__dirname, "/public"))) // Set the css and js folder to ./public
.set("views", path.join(__dirname, "/views")) // Set the ejs templates to ./views
.set("port", config.DASHBOARD.port) // Set the dashboard port
- .use(session({ secret: process.env.SESSION_PASSWORD, resave: false, saveUninitialized: false })) // Set the express session password and configuration
+ .use(
+ session({
+ secret: process.env.SESSION_PASSWORD,
+ cookie: { maxAge: 336 * 60 * 60 * 1000 },
+ name: "djs_connection_cookie",
+ resave: true,
+ saveUninitialized: false,
+ store: MongoStore.create({
+ client: db.getClient(),
+ dbName: db.name,
+ collectionName: "sessions",
+ stringify: false,
+ autoRemove: "interval",
+ autoRemoveInterval: 1,
+ }),
+ })
+ ) // Set the express session password and configuration
.use(async function (req, res, next) {
req.user = req.session.user;
req.client = client;
diff --git a/dashboard/routes/discord.js b/dashboard/routes/discord.js
index ad0c0ae62..90568a362 100644
--- a/dashboard/routes/discord.js
+++ b/dashboard/routes/discord.js
@@ -7,6 +7,12 @@ const fetch = require("node-fetch"),
// Gets login page
router.get("/login", async function (req, res) {
if (!req.user || !req.user.id || !req.user.guilds) {
+ // check if client user is ready
+ if (!req.client.user?.id) {
+ req.client.logger.debug("Client is not ready! Redirecting to /login");
+ return res.redirect("/login");
+ }
+
return res.redirect(
`https://discordapp.com/api/oauth2/authorize?client_id=${
req.client.user.id
@@ -19,7 +25,11 @@ router.get("/login", async function (req, res) {
});
router.get("/callback", async (req, res) => {
- if (!req.query.code) return res.redirect(req.client.config.DASHBOARD.failureURL);
+ if (!req.query.code) {
+ req.client.logger.debug({ query: req.query, body: req.body });
+ req.client.logger.error("Failed to login to dashboard! Check /logs folder for more details");
+ return res.redirect(req.client.config.DASHBOARD.failureURL);
+ }
if (req.query.state && req.query.state.startsWith("invite")) {
if (req.query.code) {
const guildID = req.query.state.substr("invite".length, req.query.state.length);
@@ -43,7 +53,11 @@ router.get("/callback", async (req, res) => {
// Fetch tokens (used to fetch user information's)
const tokens = await response.json();
// If the code isn't valid
- if (tokens.error || !tokens.access_token) return res.redirect(`/api/login&state=${req.query.state}`);
+ if (tokens.error || !tokens.access_token) {
+ req.client.logger.debug(tokens);
+ req.client.logger.error("Failed to login to dashboard! Check /logs folder for more details");
+ return res.redirect(`/api/login&state=${req.query.state}`);
+ }
const userData = {
infos: null,
guilds: null,
@@ -51,7 +65,7 @@ router.get("/callback", async (req, res) => {
while (!userData.infos || !userData.guilds) {
/* User infos */
if (!userData.infos) {
- response = await fetch("http://discordapp.com/api/users/@me", {
+ response = await fetch("https://discordapp.com/api/users/@me", {
method: "GET",
headers: { Authorization: `Bearer ${tokens.access_token}` },
});
diff --git a/dashboard/routes/guild-manager.js b/dashboard/routes/guild-manager.js
index 84c3b6ac6..f4c1b3635 100644
--- a/dashboard/routes/guild-manager.js
+++ b/dashboard/routes/guild-manager.js
@@ -76,27 +76,41 @@ router.post("/:serverID/basic", CheckAuth, async (req, res) => {
const settings = await getSettings(guild);
const data = req.body;
+ // BASIC CONFIGURATION
if (Object.prototype.hasOwnProperty.call(data, "basicUpdate")) {
if (data.prefix && data.prefix !== settings.prefix) {
settings.prefix = data.prefix;
}
- data.ranking = data.ranking === "on" ? true : false;
- if (data.ranking !== (settings.ranking.enabled || false)) {
- settings.ranking.enabled = data.ranking;
- }
-
data.flag_translation = data.flag_translation === "on" ? true : false;
if (data.flag_translation !== (settings.flag_translation.enabled || false)) {
settings.flag_translation.enabled = data.flag_translation;
}
- data.modlog_channel = guild.channels.cache.find((ch) => "#" + ch.name === data.modlog_channel)?.id || null;
- if (data.modlog_channel !== settings.modlog_channel) {
- settings.modlog_channel = data.modlog_channel;
+ data.invite_tracking = data.invite_tracking === "on" ? true : false;
+ if (data.invite_tracking !== (settings.invite.tracking || false)) {
+ settings.invite.tracking = data.invite_tracking;
+ }
+ }
+
+ // STATISTICS CONFIGURATION
+ if (Object.prototype.hasOwnProperty.call(data, "statsUpdate")) {
+ data.ranking = data.ranking === "on" ? true : false;
+ if (data.ranking !== (settings.stats.enabled || false)) {
+ settings.stats.enabled = data.ranking;
+ }
+
+ if (data.levelup_message && data.levelup_message !== settings.stats.xp.message) {
+ settings.stats.xp.message = data.levelup_message;
+ }
+
+ data.levelup_channel = guild.channels.cache.find((ch) => "#" + ch.name === data.levelup_channel)?.id || null;
+ if (data.levelup_channel !== settings.stats.xp.channel) {
+ settings.stats.xp.channel = data.levelup_channel;
}
}
+ // TICKET CONFIGURATION
if (Object.prototype.hasOwnProperty.call(data, "ticketUpdate")) {
if (data.limit && data.limit != settings.ticket.limit) {
settings.ticket.limit = data.limit;
@@ -108,19 +122,29 @@ router.post("/:serverID/basic", CheckAuth, async (req, res) => {
}
}
- if (Object.prototype.hasOwnProperty.call(data, "inviteUpdate")) {
- data.tracking = data.tracking === "on" ? true : false;
- if (data.tracking !== (settings.invite.tracking || false)) {
- settings.invite.tracking = data.tracking;
+ // MODERATION CONFIGURATION
+ if (Object.prototype.hasOwnProperty.call(data, "modUpdate")) {
+ if (data.max_warnings && data.max_warnings != settings.max_warn.limit) {
+ settings.max_warn.limit = data.max_warnings;
+ }
+
+ if (data.max_warn_action !== settings.max_warn.action) {
+ settings.max_warn.action = data.max_warn_action;
+ }
+
+ data.modlog_channel = guild.channels.cache.find((ch) => "#" + ch.name === data.modlog_channel)?.id || null;
+ if (data.modlog_channel !== settings.modlog_channel) {
+ settings.modlog_channel = data.modlog_channel;
}
}
+ // AUTOMOD CONFIGURATION
if (Object.prototype.hasOwnProperty.call(data, "automodUpdate")) {
- if (data.max_strikes != settings.automod.strikes) {
+ if (data.max_strikes && data.max_strikes !== settings.automod.strikes) {
settings.automod.strikes = data.max_strikes;
}
- if (data.automod_action !== settings.automod.action) {
+ if (data.automod_action && data.automod_action !== settings.automod.action) {
settings.automod.action = data.automod_action;
}
@@ -128,11 +152,14 @@ router.post("/:serverID/basic", CheckAuth, async (req, res) => {
settings.automod.max_lines = data.max_lines;
}
- if (data.max_mentions && data.max_mentions !== settings.automod.max_mentions) {
- settings.automod.max_mentions = data.max_mentions;
+ data.anti_attachments = data.anti_attachments === "on" ? true : false;
+ if (data.anti_attachments !== (settings.automod.anti_attachments || false)) {
+ settings.automod.anti_attachments = data.anti_attachments;
}
- if (data.max_role_mentions && data.max_role_mentions !== settings.automod.max_role_mentions) {
- settings.automod.max_role_mentions = data.max_role_mentions;
+
+ data.anti_invites = data.anti_invites === "on" ? true : false;
+ if (data.anti_invites !== (settings.automod.anti_invites || false)) {
+ settings.automod.anti_invites = data.anti_invites;
}
data.anti_links = data.anti_links === "on" ? true : false;
@@ -140,20 +167,27 @@ router.post("/:serverID/basic", CheckAuth, async (req, res) => {
settings.automod.anti_links = data.anti_links;
}
- data.anti_scam = data.anti_scam === "on" ? true : false;
- if (data.anti_scam !== (settings.automod.anti_scam || false)) {
- settings.automod.anti_scam = data.anti_scam;
- }
-
- data.anti_invites = data.anti_invites === "on" ? true : false;
- if (data.anti_invites !== (settings.automod.anti_invites || false)) {
- settings.automod.anti_invites = data.anti_invites;
+ data.anti_spam = data.anti_spam === "on" ? true : false;
+ if (data.anti_spam !== (settings.automod.anti_spam || false)) {
+ settings.automod.anti_spam = data.anti_spam;
}
data.anti_ghostping = data.anti_ghostping === "on" ? true : false;
if (data.anti_ghostping !== (settings.automod.anti_ghostping || false)) {
settings.automod.anti_ghostping = data.anti_ghostping;
}
+
+ data.anti_massmention = data.anti_massmention === "on" ? true : false;
+ if (data.anti_massmention !== (settings.automod.anti_massmention || false)) {
+ settings.automod.anti_massmention = data.anti_massmention;
+ }
+
+ if (data.channels?.length) {
+ if (typeof data.channels === "string") data.channels = [data.channels];
+ settings.automod.wh_channels = data.channels
+ .map((ch) => guild.channels.cache.find((c) => "#" + c.name === ch)?.id)
+ .filter((c) => c);
+ }
}
await settings.save();
@@ -185,32 +219,56 @@ router.post("/:serverID/greeting", CheckAuth, async (req, res) => {
Object.prototype.hasOwnProperty.call(data, "welcomeEnable") ||
Object.prototype.hasOwnProperty.call(data, "welcomeUpdate")
) {
+ if (data.content !== settings.welcome.content) {
+ settings.welcome.content = data.content;
+ }
+
data.content = data.content.replace(/\r?\n/g, "\\n");
if (data.content && data.content !== settings.welcome.content) {
settings.welcome.content = data.content;
}
+ if (data.description !== settings.welcome.embed.description) {
+ settings.welcome.embed.description = data.description;
+ }
+
data.description = data.description?.replaceAll(/\r\n/g, "\\n");
if (data.description && data.description !== settings.welcome.embed?.description) {
settings.welcome.embed.description = data.description;
}
+ if (data.footer !== settings.welcome.embed.footer) {
+ settings.welcome.embed.footer = data.footer;
+ }
+
if (data.footer && data.footer !== settings.welcome.embed?.footer) {
settings.welcome.embed.footer = data.footer;
}
+ if (data.hexcolor !== settings.welcome.embed.hexcolor) {
+ settings.welcome.embed.hexcolor = data.hexcolor;
+ }
+
if (data.hexcolor && data.hexcolor !== settings.welcome.embed?.color) {
settings.welcome.embed.color = data.hexcolor;
}
+ if (data.image !== settings.welcome.embed.image) {
+ settings.welcome.embed.image = data.image;
+ }
+
+ if (data.image && data.image !== settings.welcome.embed?.image) {
+ settings.welcome.embed.image = data.image;
+ }
+
data.thumbnail = data.thumbnail === "on" ? true : false;
if (data.thumbnail !== (settings.welcome.embed?.thumbnail || false)) {
settings.welcome.embed.thumbnail = data.thumbnail;
}
data.channel = guild.channels.cache.find((ch) => "#" + ch.name === data.channel)?.id;
- if (data.channel !== settings.welcome.channel_id) {
- settings.welcome.channel_id = data.channel;
+ if (data.channel !== settings.welcome.channel) {
+ settings.welcome.channel = data.channel;
}
if (!settings.welcome.enabled) settings.welcome.enabled = true;
@@ -224,32 +282,56 @@ router.post("/:serverID/greeting", CheckAuth, async (req, res) => {
Object.prototype.hasOwnProperty.call(data, "farewellEnable") ||
Object.prototype.hasOwnProperty.call(data, "farewellUpdate")
) {
+ if (data.content !== settings.farewell.content) {
+ settings.farewell.content = data.content;
+ }
+
data.content = data.content.replace(/\r?\n/g, "\\n");
if (data.content && data.content !== settings.farewell.content) {
settings.farewell.content = data.content;
}
+ if (data.description !== settings.farewell.description) {
+ settings.farewell.description = data.description;
+ }
+
data.description = data.description?.replaceAll(/\r\n/g, "\\n");
if (data.description && data.description !== settings.farewell.embed?.description) {
settings.farewell.embed.description = data.description;
}
+ if (data.footer !== settings.farewell.footer) {
+ settings.farewell.footer = data.footer;
+ }
+
if (data.footer && data.footer !== settings.farewell.embed?.footer) {
settings.farewell.embed.footer = data.footer;
}
+ if (data.hexcolor !== settings.farewell.hexcolor) {
+ settings.farewell.hexcolor = data.hexcolor;
+ }
+
if (data.hexcolor && data.hexcolor !== settings.farewell.embed?.color) {
settings.farewell.embed.color = data.hexcolor;
}
+ if (data.image !== settings.farewell.image) {
+ settings.farewell.image = data.image;
+ }
+
+ if (data.image && data.image !== settings.farewell.embed?.image) {
+ settings.farewell.embed.image = data.image;
+ }
+
data.thumbnail = data.thumbnail === "on" ? true : false;
if (data.thumbnail !== (settings.farewell.embed?.thumbnail || false)) {
settings.farewell.embed.thumbnail = data.thumbnail;
}
data.channel = guild.channels.cache.find((ch) => "#" + ch.name === data.channel)?.id;
- if (data.channel !== settings.farewell.channel_id) {
- settings.farewell.channel_id = data.channel;
+ if (data.channel !== settings.farewell.channel) {
+ settings.farewell.channel = data.channel;
}
if (!settings.farewell.enabled) settings.farewell.enabled = true;
diff --git a/dashboard/utils.js b/dashboard/utils.js
index 926b72cae..36260accb 100644
--- a/dashboard/utils.js
+++ b/dashboard/utils.js
@@ -12,8 +12,8 @@ async function fetchUser(userData, client, query) {
if (userData.guilds) {
userData.guilds.forEach((guild) => {
if (guild.permissions) {
- const perms = new Discord.Permissions(BigInt(guild.permissions));
- if (perms.has("MANAGE_GUILD")) guild.admin = true;
+ const perms = new Discord.PermissionsBitField(BigInt(guild.permissions));
+ if (perms.has("ManageGuild")) guild.admin = true;
}
guild.settingsUrl = client.guilds.cache.get(guild.id)
? `/manage/${guild.id}/`
@@ -33,7 +33,7 @@ async function fetchUser(userData, client, query) {
}
const user = await client.users.fetch(userData.id);
user.displayAvatar = user.displayAvatarURL();
- const userDb = await getUser(user.id);
+ const userDb = await getUser(user);
const userInfos = { ...user, ...userDb, ...userData, ...user.presence };
return userInfos;
}
diff --git a/dashboard/views/includes/sidebar.ejs b/dashboard/views/includes/sidebar.ejs
index f1519bf81..ad65cfb47 100644
--- a/dashboard/views/includes/sidebar.ejs
+++ b/dashboard/views/includes/sidebar.ejs
@@ -4,13 +4,12 @@