├── LICENSE ├── config.json ├── dashboard ├── index.js ├── public │ ├── css │ │ ├── home.css │ │ └── style.css │ ├── img │ │ ├── Background.png │ │ ├── close.png │ │ ├── logo.png │ │ └── menu.png │ └── js │ │ ├── app.js │ │ ├── autoResponders.js │ │ ├── commands.js │ │ ├── logger.js │ │ └── protection.js ├── routes │ ├── autoResponders.js │ ├── commands.js │ ├── home.js │ ├── index.js │ ├── logger.js │ ├── overview.js │ ├── protection.js │ └── tickets.js ├── utils │ └── index.js └── views │ ├── AutoResponders.ejs │ ├── commands.ejs │ ├── home.ejs │ ├── index.ejs │ ├── logger.ejs │ ├── overview.ejs │ ├── protection.ejs │ ├── sidebar.ejs │ └── ticket.ejs ├── index.js ├── package.json ├── src ├── admin │ ├── ban.js │ ├── clear.js │ ├── kick.js │ ├── lock.js │ ├── move.js │ ├── mute.js │ ├── role.js │ ├── rtimeout.js │ ├── setnick.js │ ├── timeout.js │ ├── unban.js │ ├── unlock.js │ └── unmute.js ├── autorole │ └── autorole.js ├── giveaway │ ├── embed.js │ ├── handling.js │ └── setup.js ├── logs │ ├── channelCreate.js │ ├── channelDelete.js │ ├── channelUpdate.js │ ├── memberBan.js │ ├── memberJoin.js │ ├── memberKick.js │ ├── memberLeft.js │ ├── memberUnban.js │ ├── messageEdit.js │ ├── messagedelete.js │ ├── nick.js │ ├── roleCreate.js │ ├── roleDelete.js │ ├── roleMember.js │ ├── roleMemberRemove.js │ ├── roleUpdate.js │ ├── voiceChannel.js │ └── voiceChannelUpdate.js ├── protection │ ├── antibanmembers.js │ ├── antibots.js │ ├── antieditrole.js │ ├── antieditserver.js │ ├── antikickmembers.js │ ├── antilinks.js │ ├── antispam.js │ ├── channels.js │ └── roles.js ├── responder │ └── autoreply.js ├── ticket │ └── ticket.js ├── user │ ├── avatar.js │ ├── banner.js │ ├── serverinfo.js │ └── userinfo.js └── utils │ └── index.js └── verify.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Wick Studio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "clientId": "bot_id", 3 | "guildId": "server_id", 4 | "autoRole": { 5 | "userRoleId": "auto_user_role_id", 6 | "botRoleId": "auto_bot_role_id" 7 | }, 8 | "ticketSettings": { 9 | "ticketSetup": { 10 | "embedColor": "#0099ff", 11 | "embedTitle": "Ticket System Setup", 12 | "embedDescription": "Click one of the buttons below to create a ticket.", 13 | "embedImage": "https://media.discordapp.net/attachments/1219719119079866498/1219854567978700850/DALLE_2024-01-07_05.36.38_-_A_stylish_banner_featuring_the_name_WICK_in_sleek_modern_letters._The_color_scheme_includes_deep_black_for_the_background_and_a_vivid_red_for_the_l.png?ex=660cd118&is=65fa5c18&hm=3255e1ca326e1e95e1177e1022aa9c0841fcec5415abfa868807b588ef24c184&=&format=webp&quality=lossless&width=687&height=392" 14 | }, 15 | "ticketGroups": {} 16 | }, 17 | "giveaways": { 18 | "enabled": "false" 19 | }, 20 | "autoResponders": [ 21 | { 22 | "trigger": "hello", 23 | "reply": "Hello, {{username}}! How can I assist you today?", 24 | "mentionUser": true 25 | }, 26 | { 27 | "trigger": "Wick Studio", 28 | "reply": "discord.gg/wicks {{user}}", 29 | "mentionUser": true 30 | } 31 | ], 32 | "protection": { 33 | "allowedGuildId": "server_id", 34 | "logChannelId": "channel_id", 35 | "whitelistRoles": [ 36 | "ROLE_ID_1", 37 | "ROLE_ID_2" 38 | ], 39 | "antispam": { 40 | "messageCount": 2, 41 | "time": 10000, 42 | "timeoutDuration": 60000, 43 | "active": "false", 44 | "deleteMessages": "false", 45 | "timeout": "false" 46 | }, 47 | "antilinks": { 48 | "actions": { 49 | "timeoutDuration": 60000, 50 | "timeout": "false", 51 | "kick": "false", 52 | "ban": "false" 53 | }, 54 | "active": "false", 55 | "deleteMessages": "false" 56 | }, 57 | "channelMonitoring": { 58 | "maxChannelChanges": 2, 59 | "timeFrame": 60000, 60 | "action": "kick", 61 | "timeoutDuration": 600000, 62 | "active": "false" 63 | }, 64 | "roleMonitoring": { 65 | "maxRoleChanges": 3, 66 | "timeFrame": 60000, 67 | "action": "timeout", 68 | "timeoutDuration": 600000, 69 | "active": "false" 70 | }, 71 | "kickMonitoring": { 72 | "maxKicks": 1, 73 | "timeFrame": 60000, 74 | "action": "kick", 75 | "timeoutDuration": 600000, 76 | "active": "false" 77 | }, 78 | "banMonitoring": { 79 | "maxBans": 1, 80 | "timeFrame": 60000, 81 | "action": "kick", 82 | "timeoutDuration": 600000, 83 | "active": "false" 84 | }, 85 | "botMonitoring": { 86 | "action": "kick", 87 | "botAction": "kick", 88 | "timeoutDuration": 600000, 89 | "active": "false" 90 | }, 91 | "roleEditMonitoring": { 92 | "maxEdits": 3, 93 | "timeFrame": 60000, 94 | "action": "timeout", 95 | "timeoutDuration": 600000, 96 | "active": "false" 97 | }, 98 | "serverEditMonitoring": { 99 | "maxEdits": 3, 100 | "timeFrame": 60000, 101 | "action": "timeout", 102 | "timeoutDuration": 600000, 103 | "active": "false" 104 | } 105 | }, 106 | "commands": { 107 | "userinfo": true, 108 | "serverinfo": true, 109 | "avatar": true, 110 | "banner": true, 111 | "clear": true, 112 | "timeout": true, 113 | "kick": true, 114 | "ban": true, 115 | "unban": true, 116 | "role": true, 117 | "rtimeout": true, 118 | "lock": true, 119 | "unlock": true, 120 | "setnick": true, 121 | "mute": true, 122 | "unmute": true, 123 | "move": true, 124 | "giveawaySetup": true 125 | }, 126 | "logger": { 127 | "enabled": true, 128 | "events": { 129 | "nicknameChangelog": "channel_id", 130 | "nicknameChange": true, 131 | "channelCreatelog": "channel_id", 132 | "channelCreate": true, 133 | "channelDeletelog": "channel_id", 134 | "channelDelete": true, 135 | "channelUpdatelog": "channel_id", 136 | "channelUpdate": true, 137 | "createrolelog": "channel_id", 138 | "roleCreate": true, 139 | "deleterolelog": "channel_id", 140 | "roleDelete": true, 141 | "roleUpdateLogChannelId": "channel_id", 142 | "roleUpdate": true, 143 | "roleMemberLogChannelId": "channel_id", 144 | "roleMember": true, 145 | "messageDeleteLogChannelId": "channel_id", 146 | "messageDelete": true, 147 | "messageEditLogChannelId": "channel_id", 148 | "messageEdit": true, 149 | "memberKicklog": "channel_id", 150 | "memberKick": true, 151 | "memberBanlog": "channel_id", 152 | "memberBan": true, 153 | "memberUnbanlog": "channel_id", 154 | "memberUnban": true, 155 | "memberJoinlog": "channel_id", 156 | "memberJoin": true, 157 | "memberLeftlog": "channel_id", 158 | "memberLeft": true, 159 | "voiceChannellog": "channel_id", 160 | "voiceChannel": true, 161 | "voiceChannelUpdatelog": "channel_id", 162 | "voiceChannelUpdate": true 163 | } 164 | } 165 | } -------------------------------------------------------------------------------- /dashboard/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const path = require('path'); 3 | const router = require('./routes'); 4 | 5 | const app = express(); 6 | 7 | // Middlewares 8 | app.use(express.static(path.join(__dirname, "public"))); 9 | app.set('view engine', 'ejs'); 10 | app.set('views', path.join(__dirname, 'views')); 11 | app.use(express.json({})); 12 | app.use(express.urlencoded({ extended: true })); 13 | 14 | // Use routes 15 | app.use(router); 16 | 17 | 18 | const { PORT } = require('../verify') 19 | app.listen(PORT, () => { 20 | console.log(`Server is running on http://localhost:${PORT}`); 21 | }); -------------------------------------------------------------------------------- /dashboard/public/css/home.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.cdnfonts.com/css/poppins"); 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | box-sizing: border-box; 6 | font-family: "Poppins", sans-serif; 7 | } 8 | .banner { 9 | position: relative; 10 | width: 100%; 11 | min-height: 100vh; 12 | padding: 0 100px; 13 | display: flex; 14 | align-items: center; 15 | background: url(../img/Background.png) no-repeat; 16 | background-position: center; 17 | background-size: cover; 18 | overflow-x: hidden; 19 | } 20 | .banner::before { 21 | content: ""; 22 | position: absolute; 23 | right: 100px; 24 | width: 500px; 25 | height: 500px; 26 | top: 50%; 27 | transform: translateY(-50%); 28 | background: #7241ff; 29 | border-radius: 50%; 30 | box-shadow: 0 0 20px #7241ff, 0 0 50px #7241ff, 0 0 150px #7241ff; 31 | transition: 1s; 32 | } 33 | .banner.active::before { 34 | background: #21283a; 35 | box-shadow: 0 0 0 1200px #141821; 36 | } 37 | header { 38 | position: fixed; 39 | top: 0; 40 | left: 0; 41 | width: 100%; 42 | z-index: 1000000000; 43 | display: flex; 44 | justify-content: space-between; 45 | align-items: center; 46 | padding: 30px 100px; 47 | } 48 | header .logo { 49 | font-size: 1.5rem; 50 | color: #fff; 51 | letter-spacing: 1px; 52 | font-weight: 600; 53 | text-transform: uppercase; 54 | text-decoration: none; 55 | transition: 0.5s; 56 | transform-origin: left; 57 | } 58 | header .logo span { 59 | color: #7241ff; 60 | border-bottom: 4px solid #7241ff; 61 | } 62 | header .toggle { 63 | position: relative; 64 | width: 30px; 65 | height: 30px; 66 | background: url(../img/menu.png); 67 | background-repeat: no-repeat; 68 | background-position: center; 69 | background-size: 30px; 70 | cursor: pointer; 71 | } 72 | header .toggle.active { 73 | background: url(../img/close.png); 74 | background-repeat: no-repeat; 75 | background-position: center; 76 | background-size: 30px; 77 | } 78 | .logoImg { 79 | position: absolute; 80 | right: 125px; 81 | width: 450px; 82 | height: 450px; 83 | top: 50%; 84 | transform: translateY(-50%); 85 | } 86 | .content { 87 | position: relative; 88 | z-index: 1; 89 | width: 100%; 90 | display: flex; 91 | justify-content: space-between; 92 | align-items: center; 93 | transition: 0.5s; 94 | transform-origin: left; 95 | } 96 | .content .contentBx { 97 | position: relative; 98 | max-width: 600px; 99 | z-index: 100; 100 | } 101 | .content .contentBx h4 { 102 | font-weight: 600; 103 | color: #7241ff; 104 | font-size: 1.5em; 105 | letter-spacing: 2px; 106 | margin-bottom: 10px; 107 | } 108 | .content .contentBx h2 { 109 | font-size: 1.5em; 110 | line-height: 1em; 111 | color: #fff; 112 | text-transform: capitalize; 113 | } 114 | .content .contentBx h3 { 115 | font-weight: 300; 116 | color: #fff; 117 | font-size: 1.8em; 118 | line-height: 1.5em; 119 | text-transform: capitalize; 120 | } 121 | .content .contentBx p { 122 | font-size: 1em; 123 | color: #fff; 124 | margin: 10px 0; 125 | margin-bottom: 20px; 126 | } 127 | .ui-btn { 128 | --btn-default-bg: #010314; 129 | --btn-padding: 15px 20px; 130 | --btn-hover-bg: rgb(51, 51, 51); 131 | --btn-transition: 0.3s; 132 | --btn-letter-spacing: 0.1rem; 133 | --btn-animation-duration: 1.2s; 134 | --btn-shadow-color: rgba(0, 0, 0, 0.137); 135 | --btn-shadow: 0 2px 10px 0 var(--btn-shadow-color); 136 | --hover-btn-color: #7241ff; 137 | --default-btn-color: #fff; 138 | --font-size: 16px; 139 | /* 👆 this field should not be empty */ 140 | --font-weight: 600; 141 | --font-family: Menlo, Roboto Mono, monospace; 142 | } 143 | 144 | /* button settings 👆 */ 145 | 146 | .ui-btn { 147 | box-sizing: border-box; 148 | padding: var(--btn-padding); 149 | display: flex; 150 | align-items: center; 151 | justify-content: center; 152 | color: var(--default-btn-color); 153 | font: var(--font-weight) var(--font-size) var(--font-family); 154 | background: var(--btn-default-bg); 155 | cursor: pointer; 156 | transition: var(--btn-transition); 157 | overflow: hidden; 158 | box-shadow: var(--btn-shadow); 159 | border-radius: 10px; 160 | border: 2px solid #2a2b3a; 161 | } 162 | 163 | .ui-btn span { 164 | letter-spacing: var(--btn-letter-spacing); 165 | transition: var(--btn-transition); 166 | box-sizing: border-box; 167 | position: relative; 168 | background: inherit; 169 | } 170 | 171 | .ui-btn span::before { 172 | box-sizing: border-box; 173 | position: absolute; 174 | content: ""; 175 | background: inherit; 176 | } 177 | 178 | .ui-btn:hover, 179 | .ui-btn:focus { 180 | background: var(--btn-default-bg); 181 | box-shadow: 0px 0px 10px 0px rgba(119, 68, 255, 0.7); 182 | border: 2px solid #7241ff; 183 | } 184 | 185 | .ui-btn:hover span, 186 | .ui-btn:focus span { 187 | color: var(--hover-btn-color); 188 | } 189 | 190 | .ui-btn:hover span::before, 191 | .ui-btn:focus span::before { 192 | animation: chitchat linear both var(--btn-animation-duration); 193 | } 194 | 195 | @keyframes chitchat { 196 | 0% { 197 | content: "#"; 198 | } 199 | 200 | 5% { 201 | content: "."; 202 | } 203 | 204 | 10% { 205 | content: "^{"; 206 | } 207 | 208 | 15% { 209 | content: "-!"; 210 | } 211 | 212 | 20% { 213 | content: "#$_"; 214 | } 215 | 216 | 25% { 217 | content: "№:0"; 218 | } 219 | 220 | 30% { 221 | content: "#{+.";}35%{content: "@}-?"; 222 | } 223 | 224 | 40% { 225 | content: "?{4@%"; 226 | } 227 | 228 | 45% { 229 | content: "=.,^!"; 230 | } 231 | 232 | 50% { 233 | content: "?2@%"; 234 | } 235 | 236 | 55% { 237 | content: "\;1}]"; 238 | } 239 | 240 | 60% { 241 | content: "?{%:%"; 242 | right: 0; 243 | } 244 | 245 | 65% { 246 | content: "|{f[4"; 247 | right: 0; 248 | } 249 | 250 | 70% { 251 | content: "{4%0%"; 252 | right: 0; 253 | } 254 | 255 | 75% { 256 | content: "'1_0<"; 257 | right: 0; 258 | } 259 | 260 | 80% { 261 | content: "{0%"; 262 | right: 0; 263 | } 264 | 265 | 85% { 266 | content: "]>'"; 267 | right: 0; 268 | } 269 | 270 | 90% { 271 | content: "4"; 272 | right: 0; 273 | } 274 | 275 | 95% { 276 | content: "2"; 277 | right: 0; 278 | } 279 | 280 | 100% { 281 | content: ""; 282 | right: 0; 283 | } 284 | } 285 | .buttons { 286 | display: flex; 287 | gap: 2rem; 288 | } 289 | .buttons a { 290 | text-decoration: none; 291 | } 292 | .banner.active .logo, 293 | .banner.active .content { 294 | transform: scale(0); 295 | } 296 | .menu { 297 | position: fixed; 298 | top: 0; 299 | left: 0; 300 | width: 100%; 301 | height: 100%; 302 | display: flex; 303 | justify-items: center; 304 | align-items: flex-start; 305 | flex-direction: column; 306 | z-index: 2; 307 | padding-left: 100px; 308 | transform: translateY(35%); 309 | opacity: 0; 310 | visibility: hidden; 311 | transition: 0.5s; 312 | } 313 | .banner.active .menu { 314 | opacity: 1; 315 | visibility: visible; 316 | transition-delay: 0.5s; 317 | } 318 | .menu li { 319 | list-style: none; 320 | } 321 | .menu li a { 322 | color: #fff; 323 | text-decoration: none; 324 | font-size: 1.5rem; 325 | padding: 5px 10px; 326 | margin: 5px 0; 327 | display: inline-block; 328 | transition: 0.25s; 329 | } 330 | .menu li:hover a { 331 | letter-spacing: 6px; 332 | background: #fff; 333 | color: #161a23; 334 | } 335 | @media (max-width: 991px) { 336 | .banner { 337 | padding: 40px; 338 | } 339 | header { 340 | padding: 20px 40px; 341 | } 342 | .banner::before { 343 | opacity: 0; 344 | } 345 | .logoImg { 346 | right: -30px; 347 | opacity: 0.3; 348 | } 349 | .menu { 350 | padding: 0; 351 | align-items: center; 352 | } 353 | .content .contentBx h2 { 354 | font-size: 1.8em; 355 | } 356 | .content .contentBx h4 { 357 | display: none; 358 | } 359 | .content .contentBx h3 { 360 | font-size: 1.2em; 361 | } 362 | } 363 | 364 | #sidebar { 365 | transition: -webkit-transform 0.3s ease-out 0s; 366 | will-change: transform; 367 | } 368 | -------------------------------------------------------------------------------- /dashboard/public/css/style.css: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | width: 7px; 3 | } 4 | ::-webkit-scrollbar-thumb:hover { 5 | background: #a3a4b492; 6 | } 7 | ::-webkit-scrollbar-thumb { 8 | background: #494a54; 9 | border-radius: 6px; 10 | } 11 | ::-webkit-scrollbar-track { 12 | background: transparent; 13 | } 14 | ::-webkit-scrollbar-thumb:active { 15 | background: #a3a4b492; 16 | } 17 | body, 18 | html { 19 | margin: 0; 20 | padding: 0; 21 | font-family: Arial, sans-serif; 22 | background: #010d19; 23 | } 24 | 25 | #navbar { 26 | width: 100%; 27 | position: fixed; 28 | background-color: #031520; 29 | color: #fff; 30 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); 31 | z-index: 1000000000; 32 | } 33 | 34 | .nav-container { 35 | max-width: 1200px; 36 | margin: 0 auto; 37 | display: flex; 38 | justify-content: space-between; 39 | align-items: center; 40 | padding: 10px 20px; 41 | } 42 | 43 | .nav-container h3 { 44 | margin: 0; 45 | padding: 0; 46 | font-size: 24px; 47 | } 48 | 49 | .logo { 50 | height: 50px; 51 | } 52 | 53 | .page { 54 | margin-left: 235px; 55 | padding: 85px 2rem; 56 | transition: margin-left 0.3s ease; 57 | } 58 | 59 | select { 60 | display: unset; 61 | } 62 | .container { 63 | background: rgba(255, 255, 255, 0.06); 64 | border-radius: 16px; 65 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); 66 | backdrop-filter: blur(0px); 67 | -webkit-backdrop-filter: blur(0px); 68 | border: 1px solid rgba(255, 255, 255, 0.31); 69 | padding: 2.5rem; 70 | } 71 | .ui-btn { 72 | --btn-default-bg: #010314; 73 | --btn-padding: 15px 20px; 74 | --btn-hover-bg: rgb(51, 51, 51); 75 | --btn-transition: 0.3s; 76 | --btn-letter-spacing: 0.1rem; 77 | --btn-animation-duration: 1.2s; 78 | --btn-shadow-color: rgba(0, 0, 0, 0.137); 79 | --btn-shadow: 0 2px 10px 0 var(--btn-shadow-color); 80 | --hover-btn-color: #7241ff; 81 | --default-btn-color: #fff; 82 | --font-size: 16px; 83 | /* 👆 this field should not be empty */ 84 | --font-weight: 600; 85 | --font-family: Menlo, Roboto Mono, monospace; 86 | } 87 | 88 | /* button settings 👆 */ 89 | 90 | .ui-btn { 91 | box-sizing: border-box; 92 | padding: var(--btn-padding); 93 | display: flex; 94 | align-items: center; 95 | justify-content: center; 96 | color: var(--default-btn-color); 97 | font: var(--font-weight) var(--font-size) var(--font-family); 98 | background: var(--btn-default-bg); 99 | cursor: pointer; 100 | transition: var(--btn-transition); 101 | overflow: hidden; 102 | box-shadow: var(--btn-shadow); 103 | border-radius: 10px; 104 | border: 2px solid #2a2b3a; 105 | } 106 | 107 | .ui-btn span { 108 | letter-spacing: var(--btn-letter-spacing); 109 | transition: var(--btn-transition); 110 | box-sizing: border-box; 111 | position: relative; 112 | background: inherit; 113 | } 114 | 115 | .ui-btn span::before { 116 | box-sizing: border-box; 117 | position: absolute; 118 | content: ""; 119 | background: inherit; 120 | } 121 | 122 | .ui-btn:hover, 123 | .ui-btn:focus { 124 | background: var(--btn-default-bg); 125 | box-shadow: 0px 0px 10px 0px rgba(119, 68, 255, 0.7); 126 | border: 2px solid #7241ff; 127 | } 128 | 129 | .ui-btn:hover span, 130 | .ui-btn:focus span { 131 | color: var(--hover-btn-color); 132 | } 133 | 134 | .ui-btn:hover span::before, 135 | .ui-btn:focus span::before { 136 | animation: chitchat linear both var(--btn-animation-duration); 137 | } 138 | 139 | @keyframes chitchat { 140 | 0% { 141 | content: "#"; 142 | } 143 | 144 | 5% { 145 | content: "."; 146 | } 147 | 148 | 10% { 149 | content: "^{"; 150 | } 151 | 152 | 15% { 153 | content: "-!"; 154 | } 155 | 156 | 20% { 157 | content: "#$_"; 158 | } 159 | 160 | 25% { 161 | content: "№:0"; 162 | } 163 | 164 | 30% { 165 | content: "#{+.";}35%{content: "@}-?"; 166 | } 167 | 168 | 40% { 169 | content: "?{4@%"; 170 | } 171 | 172 | 45% { 173 | content: "=.,^!"; 174 | } 175 | 176 | 50% { 177 | content: "?2@%"; 178 | } 179 | 180 | 55% { 181 | content: "\;1}]"; 182 | } 183 | 184 | 60% { 185 | content: "?{%:%"; 186 | right: 0; 187 | } 188 | 189 | 65% { 190 | content: "|{f[4"; 191 | right: 0; 192 | } 193 | 194 | 70% { 195 | content: "{4%0%"; 196 | right: 0; 197 | } 198 | 199 | 75% { 200 | content: "'1_0<"; 201 | right: 0; 202 | } 203 | 204 | 80% { 205 | content: "{0%"; 206 | right: 0; 207 | } 208 | 209 | 85% { 210 | content: "]>'"; 211 | right: 0; 212 | } 213 | 214 | 90% { 215 | content: "4"; 216 | right: 0; 217 | } 218 | 219 | 95% { 220 | content: "2"; 221 | right: 0; 222 | } 223 | 224 | 100% { 225 | content: ""; 226 | right: 0; 227 | } 228 | } 229 | .button { 230 | width: 150px; 231 | height: 50px; 232 | cursor: pointer; 233 | display: flex; 234 | align-items: center; 235 | background: red; 236 | border: none; 237 | border-radius: 5px; 238 | box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.15); 239 | background: #e62222; 240 | } 241 | 242 | .button, 243 | .button span { 244 | transition: 200ms; 245 | } 246 | 247 | .button .text { 248 | transform: translateX(35px); 249 | color: white; 250 | font-weight: bold; 251 | } 252 | 253 | .button .icon { 254 | position: absolute; 255 | border-left: 1px solid #c41b1b; 256 | transform: translateX(110px); 257 | height: 40px; 258 | width: 40px; 259 | display: flex; 260 | align-items: center; 261 | justify-content: center; 262 | } 263 | 264 | .button svg { 265 | width: 15px; 266 | fill: #eee; 267 | } 268 | 269 | .button:hover { 270 | background: #ff3636; 271 | } 272 | 273 | .button:hover .text { 274 | color: transparent; 275 | } 276 | 277 | .button:hover .icon { 278 | width: 150px; 279 | border-left: none; 280 | transform: translateX(0); 281 | } 282 | 283 | .button:focus { 284 | outline: none; 285 | } 286 | 287 | .button:active .icon svg { 288 | transform: scale(0.8); 289 | } 290 | .input { 291 | border: 2px solid transparent; 292 | width: 15em; 293 | height: 2.5em; 294 | padding-left: 0.8em; 295 | outline: none; 296 | overflow: hidden; 297 | background-color: #f3f3f3; 298 | border-radius: 10px; 299 | transition: all 0.5s; 300 | color: #000; 301 | } 302 | 303 | .input:hover, 304 | .input:focus { 305 | border: 2px solid #4a9dec; 306 | box-shadow: 0px 0px 0px 7px rgb(74, 157, 236, 20%); 307 | background-color: white; 308 | } 309 | .input2 { 310 | border: 2px solid transparent; 311 | width: 100%; 312 | height: 2.5em; 313 | padding-left: 0.8em; 314 | outline: none; 315 | overflow: hidden; 316 | background-color: #f3f3f3; 317 | border-radius: 10px; 318 | transition: all 0.5s; 319 | color: #000; 320 | } 321 | 322 | .input2:hover, 323 | .input2:focus { 324 | border: 2px solid #4a9dec; 325 | box-shadow: 0px 0px 0px 7px rgb(74, 157, 236, 20%); 326 | background-color: white; 327 | } 328 | .autoResponderEntry { 329 | background: rgba(255, 255, 255, 0.09); 330 | border-radius: 16px; 331 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); 332 | backdrop-filter: blur(1.4px); 333 | -webkit-backdrop-filter: blur(1.4px); 334 | border: 1px solid rgba(255, 255, 255, 0.31); 335 | } 336 | table { 337 | width: 100%; 338 | } 339 | th, 340 | td { 341 | padding: 8px; 342 | text-align: center; 343 | } 344 | td { 345 | color: #fff; 346 | } 347 | td:first-child { 348 | text-align: left; 349 | width: 15rem; 350 | } 351 | th { 352 | background-color: #f2f2f2; 353 | } 354 | th:last-child { 355 | border-radius: 0 50px 50px 0; 356 | } 357 | th:first-child { 358 | border-radius: 50px 0 0 50px; 359 | } 360 | .checkbox input[type="checkbox"] { 361 | display: none; 362 | visibility: hidden; 363 | } 364 | 365 | .checkbox .cbx { 366 | margin: auto; 367 | -webkit-user-select: none; 368 | user-select: none; 369 | cursor: pointer; 370 | } 371 | 372 | .checkbox .cbx span { 373 | display: inline-block; 374 | vertical-align: middle; 375 | transform: translate3d(0, 0, 0); 376 | } 377 | 378 | .checkbox .cbx span:first-child { 379 | position: relative; 380 | width: 18px; 381 | height: 18px; 382 | border-radius: 3px; 383 | transform: scale(1); 384 | vertical-align: middle; 385 | border: 1px solid #9098a9; 386 | transition: all 0.2s ease; 387 | } 388 | .checkbox .cbx span:first-child svg { 389 | position: absolute; 390 | top: 3px; 391 | left: 2px; 392 | fill: none; 393 | stroke: #ffffff; 394 | stroke-width: 2; 395 | stroke-linecap: round; 396 | stroke-linejoin: round; 397 | stroke-dasharray: 16px; 398 | stroke-dashoffset: 16px; 399 | transition: all 0.3s ease; 400 | transition-delay: 0.1s; 401 | transform: translate3d(0, 0, 0); 402 | } 403 | .checkbox .cbx span:first-child:before { 404 | content: ""; 405 | width: 100%; 406 | height: 100%; 407 | background: #506eec; 408 | display: block; 409 | transform: scale(0); 410 | opacity: 1; 411 | border-radius: 50%; 412 | } 413 | .checkbox .cbx:hover span:first-child { 414 | border-color: #506eec; 415 | } 416 | 417 | .checkbox .inp-cbx:checked + .cbx span:first-child { 418 | background: #506eec; 419 | border-color: #506eec; 420 | animation: wave-46 0.4s ease; 421 | } 422 | .checkbox .inp-cbx:checked + .cbx span:first-child svg { 423 | stroke-dashoffset: 0; 424 | } 425 | .checkbox .inp-cbx:checked + .cbx span:first-child:before { 426 | transform: scale(3.5); 427 | opacity: 0; 428 | transition: all 0.6s ease; 429 | } 430 | 431 | @keyframes wave-46 { 432 | 50% { 433 | transform: scale(0.9); 434 | } 435 | } 436 | .command { 437 | background: rgba(255, 255, 255, 0.09); 438 | border-radius: 16px; 439 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); 440 | backdrop-filter: blur(1.4px); 441 | -webkit-backdrop-filter: blur(1.4px); 442 | border: 1px solid rgba(255, 255, 255, 0.31); 443 | } 444 | .inputs { 445 | display: grid; 446 | grid-template-columns: repeat(2, 1fr); 447 | gap: 60px; 448 | } 449 | .input-container { 450 | position: relative; 451 | width: 25rem; 452 | } 453 | 454 | .input-container input[type="text"] { 455 | font-size: 20px; 456 | width: 100%; 457 | border: none; 458 | border-bottom: 2px solid #ccc; 459 | padding: 5px 0; 460 | background-color: transparent; 461 | outline: none; 462 | color: #ffffffa6; 463 | } 464 | 465 | .input-container .label { 466 | position: absolute; 467 | top: 0; 468 | left: 0; 469 | color: #ccc; 470 | transition: all 0.3s ease; 471 | pointer-events: none; 472 | } 473 | 474 | .input-container input[type="text"]:focus ~ .label, 475 | .input-container input[type="text"]:valid ~ .label { 476 | top: -20px; 477 | font-size: 16px; 478 | color: #fff; 479 | } 480 | .input-container .underline { 481 | position: absolute; 482 | bottom: 0; 483 | left: 0; 484 | height: 2px; 485 | width: 100%; 486 | background-color: #fff; 487 | transform: scaleX(0); 488 | transition: all 0.3s ease; 489 | } 490 | 491 | .input-container input[type="text"]:focus ~ .underline, 492 | .input-container input[type="text"]:valid ~ .underline { 493 | transform: scaleX(1); 494 | } 495 | .whitelistgrid { 496 | display: grid; 497 | grid-template-columns: 1fr 1fr 1fr 1fr; /* يمكنك تعديل عرض الأعمدة حسب الحاجة */ 498 | gap: 20px; /* يمكنك تعديل حجم الفجوة هنا */ 499 | } 500 | .radio-button-container { 501 | display: flex; 502 | flex-direction: column; 503 | margin-top: 20px; 504 | } 505 | 506 | .radio-button { 507 | display: inline-block; 508 | position: relative; 509 | cursor: pointer; 510 | } 511 | 512 | .radio-button__input { 513 | position: absolute; 514 | opacity: 0; 515 | width: 0; 516 | height: 0; 517 | } 518 | 519 | .radio-button__label { 520 | display: inline-block; 521 | padding-left: 30px; 522 | margin-bottom: 10px; 523 | position: relative; 524 | font-size: 15px; 525 | color: #f2f2f2; 526 | font-weight: 600; 527 | cursor: pointer; 528 | text-transform: uppercase; 529 | transition: all 0.3s ease; 530 | } 531 | 532 | .radio-button__custom { 533 | position: absolute; 534 | top: 0; 535 | left: 0; 536 | width: 20px; 537 | height: 20px; 538 | border-radius: 50%; 539 | border: 2px solid #555; 540 | transition: all 0.3s ease; 541 | } 542 | 543 | .radio-button__input:checked + .radio-button__label .radio-button__custom { 544 | background-color: #4c8bf5; 545 | border-color: transparent; 546 | transform: scale(0.8); 547 | box-shadow: 0 0 20px #4c8bf580; 548 | } 549 | 550 | .radio-button__input:checked + .radio-button__label { 551 | color: #4c8bf5; 552 | } 553 | 554 | .radio-button__label:hover .radio-button__custom { 555 | transform: scale(1.2); 556 | border-color: #4c8bf5; 557 | box-shadow: 0 0 20px #4c8bf580; 558 | } 559 | #open { 560 | display: none; 561 | } 562 | .commands { 563 | padding-left: 0; 564 | padding-right: 0; 565 | } 566 | .rolebutton { 567 | gap: 1rem; 568 | } 569 | @media (max-width: 768px) { 570 | #open { 571 | display: block; 572 | } 573 | .page { 574 | margin-left: 0; 575 | padding: 85px 1rem; 576 | } 577 | .inputs { 578 | display: flex; 579 | flex-direction: column; 580 | } 581 | .input-container { 582 | width: 100%; 583 | } 584 | .commands { 585 | padding-left: 0; 586 | padding-right: 0; 587 | } 588 | td:first-child { 589 | width: 0; 590 | } 591 | .whitelistgrid { 592 | display: flex; 593 | flex-direction: column; 594 | } 595 | .rolebutton { 596 | gap: 0; 597 | flex-direction: column; 598 | } 599 | .container { 600 | padding: 1.5rem; 601 | } 602 | .group { 603 | flex-direction: column; 604 | } 605 | .remove { 606 | margin-top: 15px; 607 | } 608 | } 609 | -------------------------------------------------------------------------------- /dashboard/public/img/Background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wickstudio/discord-moderator-bot/acf16ea8b5338202c1514ff43915eb64c2465930/dashboard/public/img/Background.png -------------------------------------------------------------------------------- /dashboard/public/img/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wickstudio/discord-moderator-bot/acf16ea8b5338202c1514ff43915eb64c2465930/dashboard/public/img/close.png -------------------------------------------------------------------------------- /dashboard/public/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wickstudio/discord-moderator-bot/acf16ea8b5338202c1514ff43915eb64c2465930/dashboard/public/img/logo.png -------------------------------------------------------------------------------- /dashboard/public/img/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wickstudio/discord-moderator-bot/acf16ea8b5338202c1514ff43915eb64c2465930/dashboard/public/img/menu.png -------------------------------------------------------------------------------- /dashboard/public/js/app.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wickstudio/discord-moderator-bot/acf16ea8b5338202c1514ff43915eb64c2465930/dashboard/public/js/app.js -------------------------------------------------------------------------------- /dashboard/public/js/autoResponders.js: -------------------------------------------------------------------------------- 1 | // Handling auto-respond form actions 2 | document.addEventListener("DOMContentLoaded", function () { 3 | const form = document.getElementById("autoRespondersForm"); 4 | const addAutoResponderButton = document.getElementById("addAutoResponder"); 5 | const entryTemplate = document.getElementById("entryTemplate").content; 6 | 7 | // Function to add a new autoResponder entry 8 | function addAutoResponder(autoResponder = { trigger: "", reply: "", mentionUser: true }) { 9 | const clone = document.importNode(entryTemplate, true); 10 | const removeButton = clone.querySelector(".removeAutoResponder"); 11 | 12 | clone.querySelector(".triggerInput").value = autoResponder.trigger; 13 | clone.querySelector(".replyInput").value = autoResponder.reply; 14 | clone.querySelector(".mentionUserSelect").value = autoResponder.mentionUser.toString(); 15 | 16 | // Remove button event listener 17 | removeButton.addEventListener("click", function () { 18 | removeButton.closest(".autoResponderEntry").remove(); 19 | }); 20 | 21 | form.insertBefore(clone, document.getElementById('AutoResponderButtons')); 22 | } 23 | 24 | // Add new autoResponder entry on button click 25 | addAutoResponderButton.addEventListener("click", () => addAutoResponder()); 26 | 27 | // Load initial autoResponders, for example from server or local storage 28 | const initialAutoResponders = data.autoResponders; // Assume 'data' is defined elsewhere 29 | initialAutoResponders.forEach(addAutoResponder); 30 | 31 | // const saveButton = document.getElementById("saveAutoResponders"); 32 | 33 | // Save button event listener 34 | form.addEventListener("submit", function () { 35 | const autoRespondersData = []; 36 | 37 | // Collect data from all autoResponder entries 38 | document.querySelectorAll(".autoResponderEntry").forEach((entry) => { 39 | const trigger = entry.querySelector(".triggerInput").value; 40 | const reply = entry.querySelector(".replyInput").value; 41 | const mentionUser = entry.querySelector(".mentionUserSelect").value === "true"; 42 | 43 | autoRespondersData.push({ trigger, reply, mentionUser }); 44 | }); 45 | 46 | // Submit the collected data to server 47 | fetch("/autoResponders", { 48 | method: "POST", 49 | headers: { 50 | "Content-Type": "application/json", 51 | }, 52 | body: JSON.stringify({ autoResponders: autoRespondersData }), 53 | }) 54 | .then((data) => { 55 | window.location.reload(); // Reload the page or handle success (e.g., display a success message) 56 | console.log("Success:", data); 57 | }) 58 | .catch((error) => { 59 | console.error("Error:", error); // Handle error (e.g., display an error message) 60 | }); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /dashboard/public/js/commands.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", (event) => { 2 | const form = document.getElementById("commandsForm"); 3 | 4 | form.addEventListener("submit", function (e) { 5 | e.preventDefault(); 6 | const formData = new FormData(form); 7 | const commands = {}; 8 | 9 | // Process checkboxes, setting unchecked ones to 'false' explicitly 10 | const checkboxes = form.querySelectorAll('input[type="checkbox"]'); 11 | checkboxes.forEach(checkbox => { 12 | if (!checkbox.checked) { 13 | formData.set(checkbox.name, 'false'); 14 | } 15 | }); 16 | 17 | // Convert FormData into a commands object, converting 'on' to true for checked checkboxes 18 | for (const [key, value] of formData) { 19 | commands[key] = value === "on"; 20 | } 21 | 22 | // Send the commands object to the server 23 | fetch("/commands", { 24 | method: "POST", 25 | headers: { 26 | "Content-Type": "application/json", 27 | }, 28 | body: JSON.stringify({ commands }), 29 | }) 30 | .then((data) => { 31 | window.location.reload(); // Optionally, navigate user or show success message 32 | }) 33 | .catch((error) => { 34 | console.error("There has been a problem with your fetch operation:", error); 35 | // Optionally, handle or display error to the user 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /dashboard/public/js/logger.js: -------------------------------------------------------------------------------- 1 | // Logger configuration form submission handling 2 | document.addEventListener("DOMContentLoaded", (event) => { 3 | document.getElementById("loggerForm").addEventListener("submit", async function (e) { 4 | e.preventDefault(); // Prevent traditional form submission 5 | 6 | const updatedLoggerConfig = { events: data.logger.events }; 7 | 8 | // Process checkboxes, setting their corresponding event to true or false 9 | document.querySelectorAll('input[type="checkbox"]').forEach((checkbox) => { 10 | updatedLoggerConfig.events[checkbox.name] = checkbox.checked; 11 | }); 12 | 13 | // Process text inputs, updating event log ID values 14 | document.querySelectorAll('input[type="text"]').forEach((input) => { 15 | updatedLoggerConfig.events[input.name] = input.value; 16 | }); 17 | 18 | try { 19 | // Send updated logger configuration to the server 20 | const response = await fetch("/logger", { 21 | method: "POST", 22 | headers: { 23 | "Content-Type": "application/json", 24 | }, 25 | body: JSON.stringify(updatedLoggerConfig), 26 | }); 27 | 28 | if (!response.ok) { 29 | throw new Error(`HTTP error! status: ${response.status}`); 30 | } 31 | window.location.reload(); // Reload the page or navigate user to a confirmation page 32 | 33 | } catch (error) { 34 | console.error("Error:", error); 35 | // Display error message to the user or log the error 36 | } 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /dashboard/public/js/protection.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function () { 2 | const form = document.getElementById("config.protection-form"); 3 | 4 | form.addEventListener("submit", function (e) { 5 | e.preventDefault(); 6 | const formData = new FormData(e.target); 7 | 8 | // Process checkboxes: set their values in formData based on their checked state 9 | const checkboxes = form.querySelectorAll('input[type="checkbox"]'); 10 | checkboxes.forEach(checkbox => { 11 | formData.set(checkbox.name, checkbox.checked); 12 | }); 13 | 14 | // Remove radio group entry from formData 15 | formData.delete('radio-group'); 16 | 17 | // Process radio inputs: set true or false in formData based on their checked state 18 | const radioInputs = form.querySelectorAll('input[type="radio"]'); 19 | radioInputs.forEach(radio => { 20 | formData.set(radio.value, form.querySelector(`input[value="${radio.value}"]:checked`) ? true : false); 21 | }); 22 | 23 | // Construct an object from formData entries, supporting array keys 24 | let object = {}; 25 | formData.forEach((value, key) => { 26 | const arrayKeyMatch = key.match(/^(.+)\[(\d+)\]$/); 27 | if (arrayKeyMatch) { 28 | const [, arrayKey, arrayIndex] = arrayKeyMatch; 29 | if (!Reflect.has(object, arrayKey)) { 30 | object[arrayKey] = []; 31 | } 32 | if (!Array.isArray(object[arrayKey])) { 33 | object[arrayKey] = [object[arrayKey]]; 34 | } 35 | object[arrayKey][parseInt(arrayIndex, 10)] = value; 36 | } else { 37 | if (!Reflect.has(object, key)) { 38 | object[key] = value; 39 | } else { 40 | if (!Array.isArray(object[key])) { 41 | object[key] = [object[key]]; 42 | } 43 | object[key].push(value); 44 | } 45 | } 46 | }); 47 | 48 | // Send the constructed object to the server 49 | fetch("/protection", { 50 | method: "POST", 51 | headers: { 52 | "Content-Type": "application/json", 53 | }, 54 | body: JSON.stringify(object), 55 | }) 56 | .then((data) => { 57 | console.log("Success:", data); 58 | window.location.reload(); 59 | }) 60 | .catch((error) => { 61 | console.error("Error:", error); 62 | alert("An error occurred while updating the configuration."); 63 | }); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /dashboard/routes/autoResponders.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { loadConfig, saveConfig } = require('../utils'); 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/', (req, res) => { 7 | const config = loadConfig(); 8 | res.render('index', { config, page: 'AutoResponders' }); 9 | }) 10 | 11 | router.post('/', (req, res) => { 12 | const config = loadConfig(); 13 | config.autoResponders = req.body.autoResponders; 14 | saveConfig(config); 15 | res.render('index', { config, page: 'AutoResponders' }); 16 | }); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /dashboard/routes/commands.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { loadConfig, saveConfig } = require('../utils'); 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/', (req, res) => { 7 | const config = loadConfig(); 8 | res.render('index', { config, page: 'commands' }); 9 | }); 10 | 11 | router.post('/', (req, res) => { 12 | const config = loadConfig(); 13 | config.commands = req.body.commands; 14 | saveConfig(config); 15 | res.render('index', { config, page: 'commands' }); 16 | }); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /dashboard/routes/home.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router() 3 | 4 | router.get('/', (req, res) => { 5 | res.render('home'); 6 | }); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /dashboard/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | // Routes 3 | const homeRoutes = require("./home"); 4 | const loggerRoutes = require("./logger"); 5 | const commandsRoutes = require("./commands"); 6 | const autoRespondersRoutes = require("./autoResponders"); 7 | const protectionRoutes = require("./protection"); 8 | const ticketsRoutes = require("./tickets"); 9 | const overviewRoutes = require("./overview"); 10 | 11 | const router = express.Router(); 12 | 13 | router.use("/", homeRoutes); 14 | router.use("/logger", loggerRoutes); 15 | router.use("/overview", overviewRoutes); 16 | router.use("/commands", commandsRoutes); 17 | router.use("/autoResponders", autoRespondersRoutes); 18 | router.use("/protection", protectionRoutes); 19 | router.use("/ticket", ticketsRoutes); 20 | 21 | 22 | module.exports = router; -------------------------------------------------------------------------------- /dashboard/routes/logger.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { loadConfig, saveConfig } = require('../utils'); 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/', (req, res) => { 7 | const config = loadConfig(); // Load the latest configuration 8 | res.render('index', { config, page: 'logger' }); 9 | }); 10 | 11 | router.post('/', (req, res) => { 12 | const config = loadConfig(); // Load the current configuration 13 | // Update the logger configuration 14 | config.logger.events = req.body.events; 15 | 16 | // Save the updated configuration 17 | saveConfig(config); 18 | 19 | // Send a response back to the client 20 | res.render('index', { config, page: 'logger' }); 21 | }); 22 | 23 | module.exports = router; 24 | -------------------------------------------------------------------------------- /dashboard/routes/overview.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { loadConfig, saveConfig } = require('../utils'); 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/', (req, res) => { 7 | const config = loadConfig(); 8 | res.render('index', { config, page: 'overview' }); 9 | }); 10 | 11 | router.post('/', (req, res) => { 12 | const config = loadConfig(); 13 | // Merge or overwrite the configuration as needed based on req.body 14 | Object.assign(config, req.body); 15 | saveConfig(config); 16 | res.render('index', { config, page: 'overview' }); 17 | }); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /dashboard/routes/protection.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { loadConfig, saveConfig, structureConfig } = require("../utils"); 3 | 4 | const router = express.Router(); 5 | 6 | router.get("/", (req, res) => { 7 | const config = loadConfig(); 8 | res.render("index", { config, page: "protection" }); 9 | }); 10 | 11 | router.post("/", async (req, res) => { 12 | const config = loadConfig(); 13 | const newConfig = await structureConfig(req.body); 14 | config.protection = newConfig; 15 | saveConfig(config); 16 | res.render("index", { config, page: "protection" }); 17 | }); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /dashboard/routes/tickets.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { loadConfig, saveConfig, convertTicketGroups } = require('../utils'); 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/', (req, res) => { 7 | const config = loadConfig(); 8 | res.render('index', { config, page: 'ticket' }); 9 | }); 10 | 11 | router.post('/', (req, res) => { 12 | const config = loadConfig(); 13 | const convertedGroups = convertTicketGroups(req.body.ticketGroups || {}); 14 | config.ticketSettings = { ...req.body, ticketGroups: { ...convertedGroups } }; 15 | saveConfig(config); 16 | res.render('index', { config, page: 'ticket' }); 17 | }); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /dashboard/utils/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const configPath = path.join(__dirname, '..', '..', 'config.json'); 4 | 5 | /** 6 | * Saves the updated configuration to the config.json file. 7 | * @param {Object} updatedConfig The updated configuration object. 8 | */ 9 | function saveConfig(updatedConfig) { 10 | fs.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2), 'utf8', (err) => { 11 | if (err) { 12 | console.error('Error saving the configuration:', err); 13 | throw err; // Optionally, handle this error more gracefully 14 | } 15 | console.log('Configuration saved successfully.'); 16 | }); 17 | } 18 | /** 19 | * Loads the application configuration from the config.json file. 20 | * @returns {Object} The loaded configuration object. 21 | */ 22 | function loadConfig() { 23 | try { 24 | const configData = fs.readFileSync(configPath, 'utf8'); 25 | return JSON.parse(configData); 26 | } catch (err) { 27 | console.error('Error loading the configuration:', err); 28 | throw err; // Optionally, handle this error more gracefully. 29 | } 30 | } 31 | 32 | function convertTicketGroups(originalTicketGroups) { 33 | const convertedGroups = {}; 34 | Object.values(originalTicketGroups).forEach((group) => { 35 | const { key, ...groupWithoutKey } = group; 36 | convertedGroups[key] = groupWithoutKey; 37 | }); 38 | return convertedGroups; 39 | } 40 | 41 | function structureConfig(requestBody) { 42 | const structuredConfig = {}; 43 | 44 | for (const key in requestBody) { 45 | const value = requestBody[key]; 46 | // Split the key by the period to find nested levels 47 | const keyParts = key.split("."); 48 | 49 | let currentLevel = structuredConfig; 50 | // Iterate through the parts to build the nested structure 51 | keyParts.forEach((part, index) => { 52 | // If it's the last part, assign the value 53 | if (index === keyParts.length - 1) { 54 | // Convert numeric strings to numbers where appropriate 55 | currentLevel[part] = isNaN(value) ? value : Number(value); 56 | } else { 57 | // If the next level doesn't exist, create it 58 | if (!currentLevel[part]) currentLevel[part] = {}; 59 | // Move down the structure 60 | currentLevel = currentLevel[part]; 61 | } 62 | }); 63 | } 64 | return structuredConfig 65 | } 66 | 67 | module.exports = { loadConfig, saveConfig, convertTicketGroups, structureConfig } -------------------------------------------------------------------------------- /dashboard/views/AutoResponders.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Edit AutoResponders

4 |
5 | 6 |
7 | 10 | 11 | 18 |
19 |
20 |
21 | 22 | 23 | 75 |
76 | -------------------------------------------------------------------------------- /dashboard/views/commands.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

User Info

7 |
8 | /> 10 | 17 |
18 |
19 |
20 |

Server Info

21 |
22 | /> 24 | 31 |
32 |
33 |
34 |

Avatar

35 |
36 | /> 38 | 45 |
46 |
47 |
48 |

Banner

49 |
50 | /> 52 | 59 |
60 |
61 |
62 |

Clear

63 |
64 | /> 66 | 73 |
74 |
75 | 76 |
77 |

Timeout

78 |
79 | /> 81 | 88 |
89 |
90 |
91 |

Kick

92 |
93 | /> 95 | 102 |
103 |
104 | 105 |
106 |

Ban

107 |
108 | /> 110 | 117 |
118 |
119 | 120 |
121 |

Unban

122 |
123 | /> 125 | 132 |
133 |
134 | 135 |
136 |

Role

137 |
138 | /> 140 | 147 |
148 |
149 | 150 |
151 |

Remove Timeout

152 |
153 | /> 155 | 162 |
163 |
164 | 165 |
166 |

Lock

167 |
168 | /> 170 | 177 |
178 |
179 |
180 |

Unlock

181 |
182 | /> 184 | 191 |
192 |
193 | 194 |
195 |

Set Nickname

196 |
197 | /> 199 | 206 |
207 |
208 | 209 |
210 |

Mute

211 |
212 | /> 214 | 221 |
222 |
223 | 224 |
225 |

Unmute

226 |
227 | /> 229 | 236 |
237 |
238 | 239 |
240 |

Move

241 |
242 | /> 244 | 251 |
252 |
253 |
254 |

Giveaway Setup

255 |
256 | /> 259 | 266 |
267 |
268 |
269 | 276 |
277 |
278 |
279 |
280 |
281 | -------------------------------------------------------------------------------- /dashboard/views/home.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bot Dashboard - Home 6 | 7 | 11 | 12 | 13 | 49 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /dashboard/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 23 | <% let pageScript = ''; switch (page) { case 'AutoResponders': pageScript = 24 | 'autoResponders.js'; break; case 'commands': pageScript = 'commands.js'; 25 | break; case 'logger': pageScript = 'logger.js'; break; case 'protection': 26 | pageScript = 'protection.js'; break; } %> 27 | 28 | 29 | 30 | <%- ` 31 | 34 | ` %> 35 | 39 | Wick System 40 | 41 | 42 | 43 | 61 | 62 |
63 | <%- include('sidebar') %> <% switch (page) { case 'AutoResponders': %><%- 64 | include('AutoResponders') %><% break; case 'commands': %><%- 65 | include('commands') %><% break; case 'logger': %><%- include('logger') 66 | %><% break; case 'protection': %><%- include('protection') %><% break; 67 | case 'ticket': %><%- include('ticket') %><% break; case 'overview': %><%- 68 | include('overview') %><% break; default: %><%- include('AutoResponders') 69 | %><% } %> 70 |
71 | 72 | 92 | 93 | -------------------------------------------------------------------------------- /dashboard/views/logger.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 26 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 67 | 68 | 69 | 70 | 71 | 81 | 94 | 95 | 96 | 97 | 98 | 99 | 109 | 122 | 123 | 124 | 125 | 126 | 136 | 149 | 150 | 151 | 152 | 153 | 154 | 164 | 177 | 178 | 179 | 180 | 181 | 191 | 204 | 205 | 206 | 207 | 208 | 209 | 219 | 232 | 233 | 234 | 235 | 236 | 246 | 259 | 260 | 261 | 262 | 263 | 264 | 274 | 287 | 288 | 289 | 290 | 291 | 301 | 314 | 315 | 316 | 317 | 318 | 319 | 329 | 342 | 343 | 344 | 345 | 346 | 356 | 369 | 370 | 371 | 372 | 373 | 374 | 384 | 397 | 398 | 399 | 400 | 401 | 411 | 424 | 425 | 426 | 427 | 428 | 429 | 439 | 452 | 453 | 454 | 455 | 456 | 466 | 479 | 480 | 481 |
CommandIDActive
Nickname Changelog Log ID 17 | 25 | 27 |
28 | > 31 | 37 |
38 |
Channel Create Log ID 45 | 53 | 55 |
56 | > 59 | 65 |
66 |
Channel Delete Log ID 72 | 80 | 82 |
83 | > 86 | 92 |
93 |
Channel Update Log ID 100 | 108 | 110 |
111 | > 114 | 120 |
121 |
Create Role Log ID 127 | 135 | 137 |
138 | > 141 | 147 |
148 |
Delete Role Log ID 155 | 163 | 165 |
166 | > 169 | 175 |
176 |
Role Update Log Channel ID 182 | 190 | 192 |
193 | > 196 | 202 |
203 |
Role Member Log Channel ID 210 | 218 | 220 |
221 | > 224 | 230 |
231 |
Message Delete Log Channel ID 237 | 245 | 247 |
248 | > 251 | 257 |
258 |
Message Edit Log Channel ID 265 | 273 | 275 |
276 | > 279 | 285 |
286 |
Member Kick Log ID 292 | 300 | 302 |
303 | > 306 | 312 |
313 |
Member Ban Log ID 320 | 328 | 330 |
331 | > 334 | 340 |
341 |
Member Unban Log ID 347 | 355 | 357 |
358 | > 361 | 367 |
368 |
Member Join Log ID 375 | 383 | 385 |
386 | > 389 | 395 |
396 |
Member Left Log ID 402 | 410 | 412 |
413 | > 416 | 422 |
423 |
Voice Channel Log ID 430 | 438 | 440 |
441 | > 444 | 450 |
451 |
Voice Channel Update Log ID 457 | 465 | 467 |
468 | > 471 | 477 |
478 |
482 |
483 | 490 |
491 |
492 |
493 |
494 | -------------------------------------------------------------------------------- /dashboard/views/overview.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 | 8 | 9 |
10 |
11 | 12 |
13 | 14 | 15 |
16 |
17 | 18 |
19 | 21 | 22 |
23 |
24 | 25 |
26 | 28 | 29 |
30 |
31 |
32 |
33 |
34 | 35 | 39 |
40 |
41 | 44 |
45 |
46 |
47 |
48 |
49 |
50 | -------------------------------------------------------------------------------- /dashboard/views/sidebar.ejs: -------------------------------------------------------------------------------- 1 | 59 | -------------------------------------------------------------------------------- /dashboard/views/ticket.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Edit Ticket Settings

4 |
5 |
6 |

Ticket Setup

7 |
8 | 9 | 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 | 26 |
27 |

Ticket Groups

28 |
29 | <% Object.keys(config.ticketSettings.ticketGroups).forEach(function(groupKey) { %> 30 |
31 |
32 |

Group:

33 | 34 | 35 |
36 | <% let group = config.ticketSettings.ticketGroups[groupKey]; %> 37 |
38 | 39 | 40 |
41 |
42 | 43 | 47 |
48 |
49 | 50 | 51 |
52 |
53 | 54 | 55 |
56 |
57 | 58 | 59 |
60 |
61 | 62 | 63 |
64 | 65 |
66 | <% }); %> 67 |
68 |
69 | 70 | 71 |
72 | 78 | 85 |
86 |
87 | 88 |
89 | 109 | 156 | 157 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wick-system", 3 | "version": "1.0.0", 4 | "description": "A fully featured Discord bot.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "Wick Studio", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@discordjs/builders": "^0.10.0", 13 | "@discordjs/rest": "^0.1.0-canary.0", 14 | "better-sqlite3": "^9.4.3", 15 | "chalk": "^5.3.0", 16 | "discord-api-types": "^0.25.0", 17 | "discord.js": "^14.0.0", 18 | "ms": "^2.1.3", 19 | "quick.db": "^9.1.7", 20 | "sqlite3": "^5.1.7", 21 | "body-parser": "^1.20.2", 22 | "ejs": "^3.1.9", 23 | "express": "^4.18.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/admin/ban.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('ban') 6 | .setDescription('Bans a user from the server.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to ban') 10 | .setRequired(true) 11 | ) 12 | .addStringOption(option => 13 | option.setName('reason') 14 | .setDescription('The reason for the ban') 15 | .setRequired(false) 16 | ), 17 | async execute(interaction,client) { 18 | const { commands } = client.getConfig(); 19 | if (!commands.ban) { 20 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 21 | return; 22 | } 23 | 24 | if (!interaction.member.permissions.has(PermissionFlagsBits.BanMembers)) { 25 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 26 | return; 27 | } 28 | 29 | const user = interaction.options.getUser('user'); 30 | const reason = interaction.options.getString('reason') || 'No reason provided'; 31 | 32 | try { 33 | await interaction.guild.members.ban(user.id, { reason }); 34 | await interaction.reply({ content: `${user.username} has been banned. Reason: ${reason}`, ephemeral: true }); 35 | } catch (error) { 36 | console.error('Error executing the ban command:', error); 37 | await interaction.reply({ content: 'There was an error trying to ban the user!', ephemeral: true }); 38 | } 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /src/admin/clear.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('clear') 6 | .setDescription('Clears a specified number of messages.') 7 | .addIntegerOption(option => 8 | option.setName('count') 9 | .setDescription('Number of messages to clear (1-100)') 10 | .setRequired(false) 11 | ), 12 | async execute(interaction,client) { 13 | const { commands } = client.getConfig(); 14 | if (!commands.clear) { 15 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 16 | return; 17 | } 18 | 19 | if (!interaction.member.permissions.has(PermissionFlagsBits.ManageMessages)) { 20 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 21 | return; 22 | } 23 | 24 | const count = interaction.options.getInteger('count') || 1; 25 | 26 | if (count < 1 || count > 100) { 27 | await interaction.reply({ content: 'Please specify a count between 1 and 100.', ephemeral: true }); 28 | return; 29 | } 30 | 31 | try { 32 | await interaction.channel.bulkDelete(count, true); 33 | await interaction.reply({ content: `Successfully deleted ${count} message(s).`, ephemeral: true }); 34 | } catch (error) { 35 | console.error('Error executing the clear command:', error); 36 | await interaction.reply({ content: 'There was an error trying to clear messages in this channel!', ephemeral: true }); 37 | } 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /src/admin/kick.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('kick') 6 | .setDescription('Kicks a user from the server.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to kick') 10 | .setRequired(true) 11 | ) 12 | .addStringOption(option => 13 | option.setName('reason') 14 | .setDescription('The reason for the kick') 15 | .setRequired(false) 16 | ), 17 | async execute(interaction,client) { 18 | const { commands } = client.getConfig(); 19 | if (!commands.kick) { 20 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 21 | return; 22 | } 23 | 24 | if (!interaction.member.permissions.has(PermissionFlagsBits.KickMembers)) { 25 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 26 | return; 27 | } 28 | 29 | const user = interaction.options.getUser('user'); 30 | const reason = interaction.options.getString('reason') || 'No reason provided'; 31 | 32 | try { 33 | const member = await interaction.guild.members.fetch(user.id); 34 | if (!member) throw new Error('Member not found'); 35 | 36 | await member.kick(reason); 37 | await interaction.reply({ content: `${user.username} has been kicked. Reason: ${reason}`, ephemeral: true }); 38 | } catch (error) { 39 | console.error('Error executing the kick command:', error); 40 | await interaction.reply({ content: 'There was an error trying to kick the user!', ephemeral: true }); 41 | } 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /src/admin/lock.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('lock') 6 | .setDescription('Locks the current channel, preventing members from sending messages.') 7 | .addStringOption(option => 8 | option.setName('reason') 9 | .setDescription('The reason for locking the channel') 10 | .setRequired(false)), 11 | async execute(interaction,client) { 12 | const { commands } = client.getConfig(); 13 | if (!commands.lock) { 14 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 15 | return; 16 | } 17 | 18 | if (!interaction.member.permissions.has(PermissionFlagsBits.ManageChannels)) { 19 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 20 | return; 21 | } 22 | 23 | const reason = interaction.options.getString('reason') || 'Not specified'; 24 | 25 | try { 26 | await interaction.channel.permissionOverwrites.edit(interaction.guild.roles.everyone, { SendMessages: false }, { reason }); 27 | await interaction.reply({ content: `This channel has been locked. Reason: ${reason}`, ephemeral: true }); 28 | } catch (error) { 29 | console.error('Error executing the lock command:', error); 30 | await interaction.reply({ content: 'There was an error trying to lock the channel!', ephemeral: true }); 31 | } 32 | }, 33 | }; 34 | -------------------------------------------------------------------------------- /src/admin/move.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits, ChannelType } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('move') 6 | .setDescription('Moves a user from one voice channel to another.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to move') 10 | .setRequired(true) 11 | ) 12 | .addChannelOption(option => 13 | option.setName('to') 14 | .setDescription('The voice channel to move the user to') 15 | .setRequired(true) 16 | .addChannelTypes(ChannelType.GuildVoice) 17 | ), 18 | async execute(interaction,client) { 19 | const { commands } = client.getConfig(); 20 | if (!commands.move) { 21 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 22 | return; 23 | } 24 | 25 | if (!interaction.member.permissions.has(PermissionFlagsBits.MoveMembers)) { 26 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 27 | return; 28 | } 29 | 30 | const user = interaction.options.getUser('user'); 31 | const toChannel = interaction.options.getChannel('to'); 32 | 33 | if (toChannel.type !== ChannelType.GuildVoice) { 34 | await interaction.reply({ content: 'The target channel must be a voice channel.', ephemeral: true }); 35 | return; 36 | } 37 | 38 | try { 39 | const member = await interaction.guild.members.fetch(user.id); 40 | if (!member.voice.channel) { 41 | await interaction.reply({ content: `${user.username} is not in a voice channel.`, ephemeral: true }); 42 | return; 43 | } 44 | await member.voice.setChannel(toChannel); 45 | await interaction.reply({ content: `${user.username} has been moved to ${toChannel.name}.`, ephemeral: true }); 46 | } catch (error) { 47 | console.error('Error executing the move command:', error); 48 | await interaction.reply({ content: 'There was an error trying to move the user!', ephemeral: true }); 49 | } 50 | }, 51 | }; 52 | -------------------------------------------------------------------------------- /src/admin/mute.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('mute') 6 | .setDescription('Mutes a user, preventing them from sending messages or joining voice channels.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to mute') 10 | .setRequired(true) 11 | ) 12 | .addStringOption(option => 13 | option.setName('reason') 14 | .setDescription('The reason for muting the user') 15 | .setRequired(false)), 16 | async execute(interaction,client) { 17 | const { commands } = client.getConfig(); 18 | if (!commands.mute) { 19 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 20 | return; 21 | } 22 | 23 | if (!interaction.member.permissions.has(PermissionFlagsBits.ManageRoles)) { 24 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 25 | return; 26 | } 27 | 28 | const user = interaction.options.getUser('user'); 29 | const reason = interaction.options.getString('reason') || 'No reason provided'; 30 | const mutedRole = interaction.guild.roles.cache.find(role => role.name === 'Muted'); 31 | 32 | if (!mutedRole) { 33 | await interaction.reply({ content: 'Error: Muted role not found. Please ensure a "Muted" role exists.', ephemeral: true }); 34 | return; 35 | } 36 | 37 | try { 38 | const member = await interaction.guild.members.fetch(user.id); 39 | await member.roles.add(mutedRole, reason); 40 | await interaction.reply({ content: `${user.username} has been muted. Reason: ${reason}`, ephemeral: true }); 41 | } catch (error) { 42 | console.error('Error executing the mute command:', error); 43 | await interaction.reply({ content: 'There was an error trying to mute the user!', ephemeral: true }); 44 | } 45 | }, 46 | }; 47 | -------------------------------------------------------------------------------- /src/admin/role.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('role') 6 | .setDescription('Assigns a role to a user.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to assign the role to') 10 | .setRequired(true) 11 | ) 12 | .addRoleOption(option => 13 | option.setName('role') 14 | .setDescription('The role to assign') 15 | .setRequired(true) 16 | ), 17 | async execute(interaction,client) { 18 | const { commands } = client.getConfig(); 19 | if (!commands.role) { 20 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 21 | return; 22 | } 23 | 24 | if (!interaction.member.permissions.has(PermissionFlagsBits.ManageRoles)) { 25 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 26 | return; 27 | } 28 | 29 | const user = interaction.options.getUser('user'); 30 | const role = interaction.options.getRole('role'); 31 | 32 | try { 33 | const member = await interaction.guild.members.fetch(user.id); 34 | await member.roles.add(role); 35 | await interaction.reply({ content: `${user.username} has been assigned the role ${role.name}.`, ephemeral: true }); 36 | } catch (error) { 37 | console.error('Error executing the role command:', error); 38 | await interaction.reply({ content: 'There was an error trying to assign the role to the user! Make sure the bot has the appropriate permissions and the role is not higher than the bot\'s highest role.', ephemeral: true }); 39 | } 40 | }, 41 | }; 42 | -------------------------------------------------------------------------------- /src/admin/rtimeout.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('rtimeout') 6 | .setDescription('Removes the timeout from a user.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to remove the timeout from') 10 | .setRequired(true) 11 | ), 12 | async execute(interaction,client) { 13 | const { commands } = client.getConfig(); 14 | if (!commands.rtimeout) { 15 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 16 | return; 17 | } 18 | 19 | if (!interaction.member.permissions.has(PermissionFlagsBits.ModerateMembers)) { 20 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 21 | return; 22 | } 23 | 24 | const user = interaction.options.getUser('user'); 25 | 26 | try { 27 | const member = await interaction.guild.members.fetch(user.id); 28 | await member.timeout(null); 29 | await interaction.reply({ content: `${user.username} has had their timeout removed.`, ephemeral: true }); 30 | } catch (error) { 31 | console.error('Error executing the rtimeout command:', error); 32 | await interaction.reply({ content: 'There was an error trying to remove the timeout from the user!', ephemeral: true }); 33 | } 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /src/admin/setnick.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('setnick') 6 | .setDescription('Changes a user\'s nickname.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to change the nickname for') 10 | .setRequired(true) 11 | ) 12 | .addStringOption(option => 13 | option.setName('nickname') 14 | .setDescription('The new nickname') 15 | .setRequired(true) 16 | ), 17 | async execute(interaction,client) { 18 | const { commands } = client.getConfig(); 19 | if (!commands.setnick) { 20 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 21 | return; 22 | } 23 | 24 | if (!interaction.member.permissions.has(PermissionFlagsBits.ManageNicknames)) { 25 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 26 | return; 27 | } 28 | 29 | const user = interaction.options.getUser('user'); 30 | const nickname = interaction.options.getString('nickname'); 31 | 32 | try { 33 | const member = await interaction.guild.members.fetch(user.id); 34 | await member.setNickname(nickname); 35 | await interaction.reply({ content: `${user.username}'s nickname has been changed to ${nickname}.`, ephemeral: true }); 36 | } catch (error) { 37 | console.error('Error executing the setnick command:', error); 38 | await interaction.reply({ content: 'There was an error trying to change the user\'s nickname!', ephemeral: true }); 39 | } 40 | }, 41 | }; 42 | -------------------------------------------------------------------------------- /src/admin/timeout.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('timeout') 6 | .setDescription('Times out a user for a specified duration.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to timeout') 10 | .setRequired(true) 11 | ) 12 | .addIntegerOption(option => 13 | option.setName('duration') 14 | .setDescription('Timeout duration in minutes') 15 | .setRequired(true) 16 | ), 17 | async execute(interaction,client) { 18 | const { commands } = client.getConfig(); 19 | if (!commands.timeout) { 20 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 21 | return; 22 | } 23 | 24 | if (!interaction.member.permissions.has(PermissionFlagsBits.ModerateMembers)) { 25 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 26 | return; 27 | } 28 | 29 | const user = interaction.options.getUser('user'); 30 | const duration = interaction.options.getInteger('duration'); 31 | 32 | const durationMs = duration * 60 * 1000; 33 | 34 | try { 35 | const member = await interaction.guild.members.fetch(user.id); 36 | await member.timeout(durationMs); 37 | await interaction.reply({ content: `${user.username} has been timed out for ${duration} minutes.`, ephemeral: true }); 38 | } catch (error) { 39 | console.error('Error executing the timeout command:', error); 40 | await interaction.reply({ content: 'There was an error trying to timeout the user!', ephemeral: true }); 41 | } 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /src/admin/unban.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('unban') 6 | .setDescription('Unbans a user from the server.') 7 | .addStringOption(option => 8 | option.setName('userid') 9 | .setDescription('The ID of the user to unban') 10 | .setRequired(true) 11 | ), 12 | async execute(interaction,client) { 13 | const { commands } = client.getConfig(); 14 | if (!commands.unban) { 15 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 16 | return; 17 | } 18 | 19 | if (!interaction.member.permissions.has(PermissionFlagsBits.BanMembers)) { 20 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 21 | return; 22 | } 23 | 24 | const userId = interaction.options.getString('userid'); 25 | 26 | try { 27 | await interaction.guild.bans.remove(userId); 28 | await interaction.reply({ content: `The user with ID ${userId} has been unbanned.`, ephemeral: true }); 29 | } catch (error) { 30 | console.error('Error executing the unban command:', error); 31 | await interaction.reply({ content: 'There was an error trying to unban the user! Make sure the ID is correct and the user is currently banned.', ephemeral: true }); 32 | } 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /src/admin/unlock.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('unlock') 6 | .setDescription('Unlocks the current channel, allowing members to send messages again.') 7 | .addStringOption(option => 8 | option.setName('reason') 9 | .setDescription('The reason for unlocking the channel') 10 | .setRequired(false)), 11 | async execute(interaction,client) { 12 | const { commands } = client.getConfig(); 13 | if (!commands.unlock) { 14 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 15 | return; 16 | } 17 | 18 | if (!interaction.member.permissions.has(PermissionFlagsBits.ManageChannels)) { 19 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 20 | return; 21 | } 22 | 23 | const reason = interaction.options.getString('reason') || 'Not specified'; 24 | 25 | try { 26 | await interaction.channel.permissionOverwrites.edit(interaction.guild.roles.everyone, { SendMessages: true }, { reason }); 27 | await interaction.reply({ content: `This channel has been unlocked. Reason: ${reason}`, ephemeral: true }); 28 | } catch (error) { 29 | console.error('Error executing the unlock command:', error); 30 | await interaction.reply({ content: 'There was an error trying to unlock the channel!', ephemeral: true }); 31 | } 32 | }, 33 | }; 34 | -------------------------------------------------------------------------------- /src/admin/unmute.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('unmute') 6 | .setDescription('Removes the mute from a user, allowing them to send messages and join voice channels again.') 7 | .addUserOption(option => 8 | option.setName('user') 9 | .setDescription('The user to unmute') 10 | .setRequired(true) 11 | ), 12 | async execute(interaction, client) { 13 | const { commands } = client.getConfig(); 14 | if (!commands.unmute) { 15 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 16 | return; 17 | } 18 | 19 | if (!interaction.member.permissions.has(PermissionFlagsBits.ManageRoles)) { 20 | await interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 21 | return; 22 | } 23 | 24 | const user = interaction.options.getUser('user'); 25 | const mutedRole = interaction.guild.roles.cache.find(role => role.name === 'Muted'); 26 | 27 | if (!mutedRole) { 28 | await interaction.reply({ content: 'Error: Muted role not found. Please ensure a "Muted" role exists.', ephemeral: true }); 29 | return; 30 | } 31 | 32 | try { 33 | const member = await interaction.guild.members.fetch(user.id); 34 | await member.roles.remove(mutedRole); 35 | await interaction.reply({ content: `${user.username} has been unmuted.`, ephemeral: true }); 36 | } catch (error) { 37 | console.error('Error executing the unmute command:', error); 38 | await interaction.reply({ content: 'There was an error trying to unmute the user!', ephemeral: true }); 39 | } 40 | }, 41 | }; 42 | -------------------------------------------------------------------------------- /src/autorole/autorole.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | name: 'guildMemberAdd', 4 | execute(member,client) { 5 | const { autoRole } = client.getConfig(); 6 | if (member.user.bot) { 7 | const botRole = member.guild.roles.cache.get(autoRole.botRoleId); 8 | if (botRole) { 9 | member.roles.add(botRole).catch(console.error); 10 | } else { 11 | console.log(`The bot role with ID ${autoRole.botRoleId} does not exist.`); 12 | } 13 | } else { 14 | const userRole = member.guild.roles.cache.get(autoRole.userRoleId); 15 | if (userRole) { 16 | member.roles.add(userRole).catch(console.error); 17 | } else { 18 | console.log(`The user role with ID ${autoRole.userRoleId} does not exist.`); 19 | } 20 | } 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /src/giveaway/embed.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); 2 | 3 | function createGiveawayEmbed(giveawayName, endTime, numOfWinners, joinersCount = 0) { 4 | if (isNaN(endTime) || typeof endTime !== 'number') { 5 | console.error('Invalid endTime in createGiveawayEmbed:', endTime); 6 | throw new Error('Invalid endTime provided to createGiveawayEmbed'); 7 | } 8 | 9 | const discordTimestamp = ``; 10 | 11 | const embed = new EmbedBuilder() 12 | .setTitle(`🎉 **Giveaway**: ${giveawayName} 🎉`) 13 | .setDescription("👇 **Join the giveaway by clicking the button below!** 👇") 14 | .addFields( 15 | { name: '🔚 Ends In', value: discordTimestamp, inline: true }, 16 | { name: '🏆 Winners', value: numOfWinners.toString(), inline: true }, 17 | { name: '👥 Joiners', value: joinersCount.toString(), inline: true } 18 | ) 19 | .setColor(0xFFC0CB) 20 | .setThumbnail("https://media.discordapp.net/attachments/1179553732497784906/1219443779447292098/pngtree-giveaway-in-text-banner-style-png-image_239181.png?ex=660b5285&is=65f8dd85&hm=e489122def8410fdbef8847cae24e40a9a30125d25c91ecb1833fd6fa7801305&=&format=webp&quality=lossless&width=960&height=540") 21 | .setFooter({ text: 'Hurry up! The clock is ticking.' }) 22 | .setTimestamp(new Date(endTime)); 23 | 24 | const button = new ButtonBuilder() 25 | .setCustomId('join-giveaway') 26 | .setLabel('Join Now!') 27 | .setEmoji('🎁') 28 | .setStyle(ButtonStyle.Success); 29 | 30 | const row = new ActionRowBuilder().addComponents(button); 31 | 32 | return { embed, row }; 33 | } 34 | 35 | module.exports = { createGiveawayEmbed }; -------------------------------------------------------------------------------- /src/giveaway/handling.js: -------------------------------------------------------------------------------- 1 | async function handleGiveawayError(interaction, error) { 2 | console.error('Error handling the giveaway:', error); 3 | 4 | if (error.code === 10008) { 5 | console.warn('Tried to interact with a deleted giveaway message.'); 6 | if (!interaction.replied) { 7 | await interaction.reply({ 8 | content: 'It seems the giveaway message was deleted. Please restart the giveaway.', 9 | ephemeral: true 10 | }).catch(console.error); 11 | } else { 12 | await interaction.followUp({ 13 | content: 'It seems the giveaway message was deleted. Unable to update or conclude the giveaway properly.', 14 | ephemeral: true 15 | }).catch(console.error); 16 | } 17 | } else { 18 | if (!interaction.replied) { 19 | await interaction.reply({ 20 | content: 'An error occurred while setting up the giveaway. Please try again later or contact the support team.', 21 | ephemeral: true 22 | }).catch(console.error); 23 | } else { 24 | await interaction.followUp({ 25 | content: 'An error occurred while processing the giveaway. Please check the bot’s permissions and try again.', 26 | ephemeral: true 27 | }).catch(console.error); 28 | } 29 | } 30 | } 31 | 32 | module.exports = { handleGiveawayError }; 33 | -------------------------------------------------------------------------------- /src/giveaway/setup.js: -------------------------------------------------------------------------------- 1 | const { createGiveawayEmbed } = require('./embed'); 2 | const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, PermissionsBitField } = require('discord.js'); 3 | const ms = require('ms'); 4 | const { handleGiveawayError } = require('./handling'); 5 | 6 | module.exports = { 7 | data: new SlashCommandBuilder() 8 | .setName('setup') 9 | .setDescription('Set up a giveaway.') 10 | .addStringOption(option => 11 | option.setName('time') 12 | .setDescription('The duration of the giveaway (e.g., 1m, 1h, 1d)') 13 | .setRequired(true)) 14 | .addStringOption(option => 15 | option.setName('name') 16 | .setDescription('The name of the giveaway') 17 | .setRequired(true)) 18 | .addIntegerOption(option => 19 | option.setName('winners') 20 | .setDescription('The number of winners') 21 | .setRequired(true)), 22 | 23 | async execute(interaction,client) { 24 | const config = client.getConfig(); 25 | if (!interaction.member.permissions.has(PermissionsBitField.Flags.Administrator)) { 26 | return interaction.reply({ 27 | content: 'You do not have permission to use this command.', 28 | ephemeral: true 29 | }); 30 | } 31 | 32 | if (!config.giveaways.enabled) { 33 | return interaction.reply({ 34 | content: 'The giveaway feature is currently disabled.', 35 | ephemeral: true 36 | }); 37 | } 38 | 39 | try { 40 | const time = interaction.options.getString('time'); 41 | const name = interaction.options.getString('name'); 42 | const winners = interaction.options.getInteger('winners'); 43 | if (!ms(time)) { 44 | return interaction.reply({ 45 | content: 'Invalid time format provided. Please use formats like 1m, 1h, 1d.', 46 | ephemeral: true 47 | }); 48 | } 49 | const durationMs = ms(time); 50 | const endTime = Date.now() + durationMs; 51 | 52 | let { embed, row } = createGiveawayEmbed(name, endTime, winners); 53 | const giveawayMessage = await interaction.reply({ embeds: [embed], components: [row], fetchReply: true }).catch(error => { 54 | console.error('Failed to send giveaway message:', error); 55 | handleGiveawayError(interaction, error); 56 | return null; 57 | }); 58 | 59 | if (!giveawayMessage) return; 60 | 61 | const joiners = new Set(); 62 | const filter = i => i.customId === 'join-giveaway'; 63 | const collector = interaction.channel.createMessageComponentCollector({ filter, time: durationMs }); 64 | 65 | collector.on('collect', async i => { 66 | joiners.add(i.user.id); 67 | await i.deferUpdate(); 68 | try { 69 | ({ embed } = createGiveawayEmbed(name, endTime, winners, joiners.size)); 70 | await giveawayMessage.edit({ embeds: [embed] }).catch(error => { 71 | throw error; 72 | }); 73 | } catch (error) { 74 | console.error('Failed to update giveaway message:', error); 75 | handleGiveawayError(interaction, error); 76 | collector.stop(); 77 | } 78 | }); 79 | 80 | collector.on('end', async () => { 81 | try { 82 | const winnersArray = Array.from(joiners).sort(() => 0.5 - Math.random()).slice(0, winners); 83 | const endedEmbed = new EmbedBuilder() 84 | .setTitle(`🎉 Giveaway Ended: ${name} 🎉`) 85 | .setDescription(`🏆 **Winner(s):** <@${winnersArray.join('> <@')}>`) 86 | .addFields( 87 | { name: 'Winners', value: winnersArray.length > 0 ? winnersArray.map(id => `<@${id}>`).join(', ') : 'No winners', inline: true }, 88 | { name: 'Total Participants', value: `${joiners.size}`, inline: true } 89 | ) 90 | .setColor(0x1E90FF) 91 | .setFooter({ text: 'Thank you for participating!' }); 92 | 93 | await interaction.followUp({ content: "The giveaway has ended!", embeds: [endedEmbed] }); 94 | await giveawayMessage.edit({ embeds: [endedEmbed], components: [] }).catch(error => { 95 | throw error; 96 | }); 97 | } catch (error) { 98 | console.error('Failed to conclude giveaway properly:', error); 99 | handleGiveawayError(interaction, error); 100 | } 101 | }); 102 | } catch (error) { 103 | console.error('An unexpected error occurred during the giveaway setup:', error); 104 | handleGiveawayError(interaction, error); 105 | } 106 | }, 107 | }; 108 | -------------------------------------------------------------------------------- /src/logs/channelCreate.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent, ChannelType } = require('discord.js'); 2 | 3 | function getChannelTypeString(type) { 4 | switch (type) { 5 | case ChannelType.GuildText: 6 | return 'Text'; 7 | case ChannelType.GuildVoice: 8 | return 'Voice'; 9 | case ChannelType.GuildCategory: 10 | return 'Category'; 11 | case ChannelType.GuildNews: 12 | return 'News'; 13 | case ChannelType.GuildStageVoice: 14 | return 'Stage'; 15 | case ChannelType.GuildForum: 16 | return 'Forum'; 17 | default: 18 | return 'Unknown'; 19 | } 20 | } 21 | 22 | module.exports = { 23 | name: Events.ChannelCreate, 24 | async execute(channel,client) { 25 | const config = client.getConfig(); 26 | if (!config.logger.enabled || !config.logger.events.channelCreate) { 27 | return; 28 | } 29 | 30 | const logChannelId = config.logger.events.channelCreatelog; 31 | const guild = channel.guild; 32 | const logChannel = guild.channels.cache.get(logChannelId); 33 | 34 | if (!logChannel) { 35 | console.warn(`Log channel with ID ${logChannelId} not found.`); 36 | return; 37 | } 38 | 39 | const fetchedLogs = await guild.fetchAuditLogs({ 40 | limit: 1, 41 | type: AuditLogEvent.ChannelCreate, 42 | }).catch(console.error); 43 | 44 | let executor = 'Unknown'; 45 | let creationTime = ``; 46 | if (fetchedLogs && fetchedLogs.entries.size > 0) { 47 | const channelCreateLog = fetchedLogs.entries.first(); 48 | if (channelCreateLog && channelCreateLog.target.id === channel.id) { 49 | executor = channelCreateLog.executor ? channelCreateLog.executor.toString() : 'Unknown'; 50 | } 51 | } 52 | 53 | const embed = new EmbedBuilder() 54 | .setColor(0x3498DB) 55 | .setTitle('Channel Created') 56 | .addFields( 57 | { name: 'Channel', value: channel.toString(), inline: true }, 58 | { name: 'Type', value: getChannelTypeString(channel.type), inline: true }, 59 | { name: 'Created By', value: executor, inline: true }, 60 | { name: 'Creation Time', value: creationTime, inline: false } 61 | ) 62 | .setTimestamp() 63 | .setFooter({ text: `Channel ID: ${channel.id}` }); 64 | 65 | try { 66 | await logChannel.send({ embeds: [embed] }); 67 | } catch (error) { 68 | console.error(`Failed to send channel creation log in guild: ${guild.id}`, error); 69 | } 70 | }, 71 | }; 72 | -------------------------------------------------------------------------------- /src/logs/channelDelete.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent, ChannelType } = require('discord.js'); 2 | 3 | function getChannelTypeString(type) { 4 | switch (type) { 5 | case ChannelType.GuildText: return 'Text'; 6 | case ChannelType.GuildVoice: return 'Voice'; 7 | case ChannelType.GuildCategory: return 'Category'; 8 | case ChannelType.GuildNews: return 'News'; 9 | case ChannelType.GuildStageVoice: return 'Stage'; 10 | case ChannelType.GuildForum: return 'Forum'; 11 | default: return 'Unknown'; 12 | } 13 | } 14 | 15 | module.exports = { 16 | name: Events.ChannelDelete, 17 | async execute(channel,client) { 18 | const config = client.getConfig(); 19 | if (!config.logger.enabled || !config.logger.events.channelDelete) { 20 | return; 21 | } 22 | 23 | const guild = channel.guild; 24 | const logChannelId = config.logger.events.channelDeletelog; 25 | const logChannel = guild.channels.cache.get(logChannelId); 26 | 27 | if (!logChannel) { 28 | console.warn(`Log channel with ID ${logChannelId} not found.`); 29 | return; 30 | } 31 | 32 | const fetchedLogs = await guild.fetchAuditLogs({ 33 | limit: 1, 34 | type: AuditLogEvent.ChannelDelete, 35 | }).catch(console.error); 36 | 37 | let executor = 'Unknown'; 38 | if (fetchedLogs && fetchedLogs.entries.size > 0) { 39 | const channelDeleteLog = fetchedLogs.entries.first(); 40 | if (channelDeleteLog && channelDeleteLog.target.id === channel.id) { 41 | executor = channelDeleteLog.executor ? channelDeleteLog.executor.toString() : 'Unknown'; 42 | } 43 | } 44 | 45 | const embed = new EmbedBuilder() 46 | .setColor(0x3498DB) 47 | .setTitle('Channel Deleted') 48 | .addFields( 49 | { name: 'Channel Name', value: channel.name, inline: true }, 50 | { name: 'Type', value: getChannelTypeString(channel.type), inline: true }, 51 | { name: 'Deleted By', value: executor, inline: true } 52 | ) 53 | .setTimestamp() 54 | .setFooter({ text: `Channel ID: ${channel.id}` }); 55 | 56 | try { 57 | await logChannel.send({ embeds: [embed] }); 58 | } catch (error) { 59 | console.error(`Failed to send channel deletion log in guild: ${guild.id}`, error); 60 | } 61 | }, 62 | }; 63 | -------------------------------------------------------------------------------- /src/logs/channelUpdate.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.ChannelUpdate, 5 | async execute(oldChannel, newChannel,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.channelUpdate) { 8 | return; 9 | } 10 | 11 | const guild = newChannel.guild; 12 | const logChannelId = config.logger.events.channelUpdatelog; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | 15 | 16 | if (!logChannel) { 17 | console.warn(`Log channel with ID ${logChannelId} not found.`); 18 | return; 19 | } 20 | 21 | let changes = []; 22 | 23 | const addChange = (name, oldValue, newValue) => { 24 | changes.push({ name: `**${name}**`, value: `**From:** ${oldValue}\n**To:** ${newValue}`, inline: false }); 25 | }; 26 | 27 | if (oldChannel.name !== newChannel.name) { 28 | addChange('Name', oldChannel.name, newChannel.name); 29 | } 30 | if (oldChannel.topic !== newChannel.topic) { 31 | addChange('Topic', oldChannel.topic || '`None`', newChannel.topic || '`None`'); 32 | } 33 | if (oldChannel.nsfw !== newChannel.nsfw) { 34 | addChange('NSFW', oldChannel.nsfw ? 'Enabled' : 'Disabled', newChannel.nsfw ? 'Enabled' : 'Disabled'); 35 | } 36 | if (oldChannel.rateLimitPerUser !== newChannel.rateLimitPerUser) { 37 | addChange('Slowmode', `${oldChannel.rateLimitPerUser} seconds`, `${newChannel.rateLimitPerUser} seconds`); 38 | } 39 | 40 | if (oldChannel.parentId !== newChannel.parentId) { 41 | const oldParentName = oldChannel.guild.channels.cache.get(oldChannel.parentId)?.name || 'None'; 42 | const newParentName = newChannel.guild.channels.cache.get(newChannel.parentId)?.name || 'None'; 43 | addChange('Category', oldParentName, newParentName); 44 | } 45 | 46 | if (changes.length === 0) { 47 | return; 48 | } 49 | 50 | const embed = new EmbedBuilder() 51 | .setColor(0xFFA500) 52 | .setTitle(`🔄 Channel Updated Log`) 53 | .setDescription(`Updates detected in ${newChannel.toString()}.`) 54 | .addFields(changes) 55 | .setTimestamp() 56 | .setFooter({ text: `Channel ID: ${newChannel.id}` }); 57 | 58 | try { 59 | const fetchedLogs = await guild.fetchAuditLogs({ limit: 1, type: AuditLogEvent.ChannelUpdate }); 60 | if (fetchedLogs && fetchedLogs.entries.size > 0) { 61 | const channelUpdateLog = fetchedLogs.entries.first(); 62 | if (channelUpdateLog && channelUpdateLog.target.id === newChannel.id) { 63 | const executor = channelUpdateLog.executor ? channelUpdateLog.executor.toString() : 'Unknown'; 64 | embed.addFields({ name: '**Updated By**', value: executor, inline: false }); 65 | } 66 | } 67 | 68 | await logChannel.send({ embeds: [embed] }); 69 | } catch (error) { 70 | console.error(`Failed to send channel update log in guild: ${guild.id}`, error); 71 | } 72 | }, 73 | }; 74 | -------------------------------------------------------------------------------- /src/logs/memberBan.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.GuildBanAdd, 5 | async execute(ban,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.memberBan) { 8 | return; 9 | } 10 | 11 | const guild = ban.guild; 12 | const logChannelId = config.logger.events.memberBanlog; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | 15 | if (!logChannel) { 16 | console.warn(`Log channel with ID ${logChannelId} not found.`); 17 | return; 18 | } 19 | 20 | const auditLogs = await guild.fetchAuditLogs({ type: AuditLogEvent.MemberBanAdd }); 21 | const banLog = auditLogs.entries.find(entry => 22 | entry.target.id === ban.user.id && 23 | (Date.now() - entry.createdTimestamp) < 10000 24 | ); 25 | 26 | const executor = banLog ? banLog.executor.tag : 'Unknown'; 27 | const reason = banLog && banLog.reason ? banLog.reason : 'No reason provided'; 28 | 29 | const embed = new EmbedBuilder() 30 | .setColor(0xFF0000) 31 | .setTitle('Member Banned') 32 | .setDescription(`${ban.user.tag} was banned from the server.`) 33 | .addFields( 34 | { name: 'User', value: `${ban.user}` }, 35 | { name: 'Banned By', value: `${executor}` }, 36 | { name: 'Reason', value: `${reason}` } 37 | ) 38 | .setTimestamp() 39 | .setFooter({ text: `User ID: ${ban.user.id}`, iconURL: ban.user.displayAvatarURL() }); 40 | 41 | try { 42 | await logChannel.send({ embeds: [embed] }); 43 | } catch (error) { 44 | console.error(`Failed to send member ban log in guild: ${guild.id}`, error); 45 | } 46 | }, 47 | }; 48 | -------------------------------------------------------------------------------- /src/logs/memberJoin.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events } = require('discord.js'); 2 | const config = require('../../config'); 3 | 4 | module.exports = { 5 | name: Events.GuildMemberAdd, 6 | async execute(member,client) { 7 | const config = client.getConfig(); 8 | if (!config.logger.enabled || !config.logger.events.memberJoin) { 9 | return; 10 | } 11 | 12 | const guild = member.guild; 13 | const logChannelId = config.logger.events.memberJoinlog; 14 | const logChannel = guild.channels.cache.get(logChannelId); 15 | 16 | if (!logChannel) { 17 | console.warn(`Log channel with ID ${logChannelId} not found.`); 18 | return; 19 | } 20 | 21 | const embed = new EmbedBuilder() 22 | .setColor(0x00FF00) 23 | .setTitle('Member Joined') 24 | .setDescription(`${member.user.tag} has joined the server.`) 25 | .setThumbnail(member.user.displayAvatarURL()) 26 | .addFields( 27 | { name: 'Account Created', value: ``, inline: true }, 28 | { name: 'Member Count', value: `${guild.memberCount}`, inline: true } 29 | ) 30 | .setTimestamp(); 31 | 32 | try { 33 | await logChannel.send({ embeds: [embed] }); 34 | } catch (error) { 35 | console.error(`Failed to send member join log in guild: ${guild.id}`, error); 36 | } 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /src/logs/memberKick.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.GuildMemberRemove, 5 | async execute(member,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.memberKick) { 8 | return; 9 | } 10 | 11 | const guild = member.guild; 12 | const logChannelId = config.logger.events.memberKicklog; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | 15 | if (!logChannel) { 16 | console.warn(`Log channel with ID ${logChannelId} not found.`); 17 | return; 18 | } 19 | 20 | setTimeout(async () => { 21 | const auditLogs = await guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick }); 22 | const kickLog = auditLogs.entries.find(entry => 23 | entry.target.id === member.id && 24 | (Date.now() - entry.createdTimestamp) < 10000 25 | ); 26 | 27 | if (!kickLog) return; 28 | 29 | const executor = kickLog.executor.tag; 30 | const reason = kickLog.reason || 'No reason provided'; 31 | 32 | const embed = new EmbedBuilder() 33 | .setColor(0xFFA500) 34 | .setTitle('Member Kicked') 35 | .setDescription(`${member.user.tag} was kicked from the server.`) 36 | .addFields( 37 | { name: 'User', value: `${member.user}` }, 38 | { name: 'Kicked By', value: `${executor}` }, 39 | { name: 'Reason', value: `${reason}` } 40 | ) 41 | .setTimestamp() 42 | .setFooter({ text: `User ID: ${member.id}`, iconURL: member.user.displayAvatarURL() }); 43 | 44 | try { 45 | await logChannel.send({ embeds: [embed] }); 46 | } catch (error) { 47 | console.error(`Failed to send member kick log in guild: ${guild.id}`, error); 48 | } 49 | }, 1000); 50 | }, 51 | }; 52 | -------------------------------------------------------------------------------- /src/logs/memberLeft.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.GuildMemberRemove, 5 | async execute(member,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.memberLeft) { 8 | return; 9 | } 10 | 11 | const guild = member.guild; 12 | const logChannelId = config.logger.events.memberLeftlog; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | 15 | if (!logChannel) { 16 | console.warn(`Log channel with ID ${logChannelId} not found.`); 17 | return; 18 | } 19 | 20 | let leaveReason = 'Left the server'; 21 | 22 | const embed = new EmbedBuilder() 23 | .setColor(0xFF0000) 24 | .setTitle('Member Left') 25 | .setDescription(`${member.user.tag} (${member.user.id}) has left the server.`) 26 | .setThumbnail(member.user.displayAvatarURL()) 27 | .addFields( 28 | { name: 'Reason', value: leaveReason }, 29 | { name: 'Member Count', value: `${guild.memberCount}` } 30 | ) 31 | .setTimestamp(); 32 | 33 | try { 34 | await logChannel.send({ embeds: [embed] }); 35 | } catch (error) { 36 | console.error(`Failed to send member leave log in guild: ${guild.id}`, error); 37 | } 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /src/logs/memberUnban.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.GuildBanRemove, 5 | async execute(ban,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.memberUnban) { 8 | return; 9 | } 10 | 11 | const guild = ban.guild; 12 | const logChannelId = config.logger.events.memberUnbanlog; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | 15 | if (!logChannel) { 16 | console.warn(`Log channel with ID ${logChannelId} not found.`); 17 | return; 18 | } 19 | 20 | const auditLogs = await guild.fetchAuditLogs({ type: AuditLogEvent.MemberBanRemove }); 21 | const unbanLog = auditLogs.entries.find(entry => 22 | entry.target.id === ban.user.id && 23 | (Date.now() - entry.createdTimestamp) < 10000 24 | ); 25 | 26 | const executor = unbanLog ? unbanLog.executor.tag : 'Unknown'; 27 | const reason = unbanLog && unbanLog.reason ? unbanLog.reason : 'No reason provided'; 28 | 29 | const embed = new EmbedBuilder() 30 | .setColor(0x00FF00) 31 | .setTitle('Member Unbanned') 32 | .setDescription(`${ban.user.tag} was unbanned from the server.`) 33 | .addFields( 34 | { name: 'User', value: `${ban.user}` }, 35 | { name: 'Unbanned By', value: `${executor}` }, 36 | { name: 'Reason', value: `${reason}` } 37 | ) 38 | .setTimestamp() 39 | .setFooter({ text: `User ID: ${ban.user.id}`, iconURL: ban.user.displayAvatarURL() }); 40 | 41 | try { 42 | await logChannel.send({ embeds: [embed] }); 43 | } catch (error) { 44 | console.error(`Failed to send member unban log in guild: ${guild.id}`, error); 45 | } 46 | }, 47 | }; 48 | -------------------------------------------------------------------------------- /src/logs/messageEdit.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.MessageUpdate, 5 | async execute(oldMessage, newMessage,client) { 6 | const config = client.getConfig(); 7 | if (newMessage.author.bot || newMessage.system || oldMessage.content === newMessage.content) return; 8 | 9 | const guild = newMessage.guild; 10 | const logChannelId = config.logger.events.messageEditLogChannelId; 11 | 12 | if (!config.logger.enabled || !config.logger.events.messageEdit || !logChannelId) { 13 | return; 14 | } 15 | 16 | const logChannel = guild.channels.cache.get(logChannelId); 17 | if (!logChannel) { 18 | console.warn(`Log channel with ID ${logChannelId} not found.`); 19 | return; 20 | } 21 | 22 | const embed = new EmbedBuilder() 23 | .setColor(0xFFFF00) 24 | .setTitle('Message Edited') 25 | .setDescription(`A message by ${newMessage.author} was edited in ${newMessage.channel}.`) 26 | .addFields( 27 | { name: 'Before', value: oldMessage.content?.substring(0, 1024) || 'No content (message might have been an embed or attachment)' }, 28 | { name: 'After', value: newMessage.content?.substring(0, 1024) || 'No content (message might have been an embed or attachment)' } 29 | ) 30 | .setTimestamp() 31 | .setFooter({ text: `Author ID: ${newMessage.author.id}`, iconURL: newMessage.author.displayAvatarURL() }); 32 | 33 | try { 34 | await logChannel.send({ embeds: [embed] }); 35 | } catch (error) { 36 | console.error(`Failed to send message edit log in guild: ${guild.id}`, error); 37 | } 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /src/logs/messagedelete.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.MessageDelete, 5 | async execute(message,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.messageDelete) { 8 | return; 9 | } 10 | 11 | if (message.author.bot || message.system) return; 12 | 13 | const guild = message.guild; 14 | const logChannelId = config.logger.events.messageDeleteLogChannelId; 15 | const logChannel = guild.channels.cache.get(logChannelId); 16 | 17 | if (!logChannel) { 18 | console.warn(`Log channel with ID ${logChannelId} not found.`); 19 | return; 20 | } 21 | 22 | let executor = 'Unknown'; 23 | 24 | setTimeout(async () => { 25 | try { 26 | const auditLogs = await guild.fetchAuditLogs({ type: AuditLogEvent.MessageDelete }); 27 | const deleteLog = auditLogs.entries.first(); 28 | if (deleteLog) { 29 | const target = deleteLog.target; 30 | if (target.id === message.author.id) { 31 | executor = deleteLog.executor.tag; 32 | } 33 | } 34 | } catch (error) { 35 | console.error('Error while fetching audit logs:', error); 36 | } 37 | 38 | const embed = new EmbedBuilder() 39 | .setColor(0xFF0000) 40 | .setTitle('Message Deleted') 41 | .setDescription(`A message by ${message.author} was deleted in ${message.channel}.`) 42 | .addFields( 43 | { name: 'Content', value: message.content?.substring(0, 1024) || 'No content (may be an embed or attachment)' }, 44 | { name: 'Deleted By', value: executor }, 45 | { name: 'Message ID', value: message.id } 46 | ) 47 | .setTimestamp(); 48 | 49 | try { 50 | await logChannel.send({ embeds: [embed] }); 51 | } catch (error) { 52 | console.error(`Failed to send message delete log in guild: ${guild.id}`, error); 53 | } 54 | }, 1000); 55 | }, 56 | }; 57 | -------------------------------------------------------------------------------- /src/logs/nick.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.GuildMemberUpdate, 5 | async execute(oldMember, newMember,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.nicknameChange) { 8 | return; 9 | } 10 | 11 | const loggerChannelId = config.logger.events.nicknameChangelog; 12 | const guild = newMember.guild; 13 | const logChannel = guild.channels.cache.get(loggerChannelId); 14 | 15 | if (!logChannel) { 16 | console.warn(`Log channel with ID ${loggerChannelId} not found.`); 17 | return; 18 | } 19 | 20 | if (oldMember.nickname === newMember.nickname) { 21 | return; 22 | } 23 | 24 | const fetchedLogs = await guild.fetchAuditLogs({ 25 | limit: 1, 26 | type: AuditLogEvent.MemberUpdate, 27 | }).catch(console.error); 28 | 29 | let executor = 'Unknown'; 30 | let timestampField = 'Just now'; 31 | if (fetchedLogs) { 32 | const nicknameChangeLog = fetchedLogs.entries.first(); 33 | if (nicknameChangeLog) { 34 | const target = nicknameChangeLog.target; 35 | if (target.id === newMember.id && (oldMember.nickname !== newMember.nickname)) { 36 | executor = `<@${nicknameChangeLog.executor.id}>`; 37 | const timestamp = Math.floor(nicknameChangeLog.createdAt / 1000); 38 | timestampField = ``; 39 | } 40 | } 41 | } 42 | 43 | const embed = new EmbedBuilder() 44 | .setColor(0x3498DB) 45 | .setTitle('Nickname Change') 46 | .addFields( 47 | { name: 'User', value: `<@${newMember.id}>`, inline: true }, 48 | { name: 'Old Nickname', value: oldMember.nickname || '`None`', inline: true }, 49 | { name: 'New Nickname', value: newMember.nickname || '`None`', inline: true }, 50 | { name: 'Changed By', value: executor, inline: true }, 51 | { name: 'When', value: timestampField, inline: true }, 52 | ) 53 | .setFooter({ text: 'User ID: ' + newMember.id }); 54 | 55 | try { 56 | await logChannel.send({ embeds: [embed] }); 57 | } catch (error) { 58 | console.error(`Failed to send nickname change log in guild: ${guild.id}`, error); 59 | } 60 | }, 61 | }; 62 | -------------------------------------------------------------------------------- /src/logs/roleCreate.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.RoleCreate, 5 | async execute(role,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.roleCreate) { 8 | return; 9 | } 10 | 11 | const guild = role.guild; 12 | const logChannelId = config.logger.events.createrolelog; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | const creationTime = Math.floor(role.createdTimestamp / 1000); 15 | 16 | if (!logChannel) { 17 | console.warn(`Log channel with ID ${logChannelId} not found.`); 18 | return; 19 | } 20 | 21 | const fetchedLogs = await guild.fetchAuditLogs({ 22 | limit: 1, 23 | type: AuditLogEvent.RoleCreate, 24 | }).catch(console.error); 25 | 26 | let executor = 'Unknown'; 27 | if (fetchedLogs && fetchedLogs.entries.size > 0) { 28 | const roleCreateLog = fetchedLogs.entries.first(); 29 | if (roleCreateLog) { 30 | executor = `<@${roleCreateLog.executor.id}>`; 31 | } 32 | } 33 | 34 | const embed = new EmbedBuilder() 35 | .setColor(role.color || 0xFFFFFF) 36 | .setTitle('Role Created') 37 | .setDescription(`A new role has been created.`) 38 | .addFields( 39 | { name: 'Role', value: role.toString(), inline: true }, 40 | { name: 'Created By', value: executor, inline: true }, 41 | { name: 'Creation Time', value: ``, inline: false } 42 | ) 43 | .setTimestamp() 44 | .setFooter({ text: `Role ID: ${role.id}` }); 45 | 46 | try { 47 | await logChannel.send({ embeds: [embed] }); 48 | } catch (error) { 49 | console.error(`Failed to send role creation log in guild: ${guild.id}`, error); 50 | } 51 | }, 52 | }; 53 | -------------------------------------------------------------------------------- /src/logs/roleDelete.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.RoleDelete, 5 | async execute(role,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.roleDelete) { 8 | return; 9 | } 10 | 11 | const guild = role.guild; 12 | const logChannelId = config.logger.events.deleterolelog; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | const deletionTime = Math.floor(Date.now() / 1000); 15 | 16 | if (!logChannel) { 17 | console.warn(`Log channel with ID ${logChannelId} not found.`); 18 | return; 19 | } 20 | 21 | const fetchedLogs = await guild.fetchAuditLogs({ 22 | limit: 1, 23 | type: AuditLogEvent.RoleDelete, 24 | }).catch(console.error); 25 | 26 | let executor = 'Unknown'; 27 | if (fetchedLogs && fetchedLogs.entries.size > 0) { 28 | const roleDeleteLog = fetchedLogs.entries.first(); 29 | if (roleDeleteLog) { 30 | executor = `<@${roleDeleteLog.executor.id}>`; 31 | } 32 | } 33 | 34 | const embed = new EmbedBuilder() 35 | .setColor(0xFF0000) 36 | .setTitle('Role Deleted') 37 | .setDescription(`A role was deleted.`) 38 | .addFields( 39 | { name: 'Role Name', value: role.name, inline: true }, 40 | { name: 'Deleted By', value: executor, inline: true }, 41 | { name: 'Deletion Time', value: ``, inline: false } 42 | ) 43 | .setTimestamp() 44 | .setFooter({ text: `Role ID: ${role.id}` }); 45 | 46 | try { 47 | await logChannel.send({ embeds: [embed] }); 48 | } catch (error) { 49 | console.error(`Failed to send role deletion log in guild: ${guild.id}`, error); 50 | } 51 | }, 52 | }; 53 | -------------------------------------------------------------------------------- /src/logs/roleMember.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.GuildMemberUpdate, 5 | async execute(oldMember, newMember,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.roleMember) { 8 | return; 9 | } 10 | 11 | const guild = newMember.guild; 12 | const logChannelId = config.logger.events.roleMemberLogChannelId; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | 15 | if (!logChannel) { 16 | console.warn(`Role member log channel with ID ${logChannelId} not found.`); 17 | return; 18 | } 19 | 20 | const oldRoles = oldMember.roles.cache; 21 | const newRoles = newMember.roles.cache; 22 | const addedRoles = newRoles.filter(role => !oldRoles.has(role.id)); 23 | const removedRoles = oldRoles.filter(role => !newRoles.has(role.id)); 24 | 25 | if (addedRoles.size === 0 && removedRoles.size === 0) return; 26 | 27 | const fetchedLogs = await guild.fetchAuditLogs({ 28 | limit: 1, 29 | type: addedRoles.size > 0 ? AuditLogEvent.MemberRoleUpdate : AuditLogEvent.MemberRoleUpdate, 30 | }).catch(console.error); 31 | 32 | let executor = 'Unknown'; 33 | if (fetchedLogs && fetchedLogs.entries.size > 0) { 34 | const roleChangeLog = fetchedLogs.entries.first(); 35 | if (roleChangeLog && roleChangeLog.target.id === newMember.id) { 36 | executor = roleChangeLog.executor ? `<@${roleChangeLog.executor.id}>` : 'Unknown'; 37 | } 38 | } 39 | 40 | const embed = new EmbedBuilder() 41 | .setColor(0x3498DB) 42 | .setTitle('Role Update') 43 | .setDescription(`Roles updated for ${newMember.toString()}`) 44 | .addFields( 45 | { name: 'Role Added', value: addedRoles.map(role => role.toString()).join('\n') || 'None', inline: true }, 46 | { name: 'Role Removed', value: removedRoles.map(role => role.toString()).join('\n') || 'None', inline: true }, 47 | { name: 'Updated By', value: executor, inline: false } 48 | ) 49 | .setTimestamp() 50 | .setFooter({ text: `User ID: ${newMember.id}` }); 51 | 52 | try { 53 | await logChannel.send({ embeds: [embed] }); 54 | } catch (error) { 55 | console.error(`Failed to send role member update log in guild: ${guild.id}`, error); 56 | } 57 | }, 58 | }; 59 | -------------------------------------------------------------------------------- /src/logs/roleMemberRemove.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.GuildMemberUpdate, 5 | async execute(oldMember, newMember,client) { 6 | const config = client.getConfig(); 7 | if (!config.logger.enabled || !config.logger.events.roleMemberRemove) { 8 | return; 9 | } 10 | 11 | const guild = newMember.guild; 12 | const logChannelId = config.logger.events.roleMemberRemovelog; 13 | const logChannel = guild.channels.cache.get(logChannelId); 14 | 15 | if (!logChannel) return console.warn(`Role member remove log channel with ID ${logChannelId} not found.`); 16 | 17 | const embed = new EmbedBuilder() 18 | .setTitle('Role Removed from User') 19 | .setColor(0xFF0000) 20 | .setDescription(`${newMember.user.tag} had role(s) removed.`) 21 | .addFields( 22 | { name: 'Removed Roles', value: [...removedRoles.values()].map(role => role.name).join(', '), inline: true } 23 | ) 24 | .setTimestamp(); 25 | 26 | logChannel.send({ embeds: [embed] }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /src/logs/roleUpdate.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent, PermissionsBitField } = require('discord.js'); 2 | 3 | function formatPermissions(permissions) { 4 | const formattedPermissions = new PermissionsBitField(permissions).toArray(); 5 | return formattedPermissions.length > 0 ? formattedPermissions.join(', ') : 'None'; 6 | } 7 | 8 | module.exports = { 9 | name: Events.RoleUpdate, 10 | async execute(oldRole, newRole,client) { 11 | const config = client.getConfig(); 12 | if (!config.logger.enabled || !config.logger.events.roleUpdate) { 13 | return; 14 | } 15 | 16 | const guild = newRole.guild; 17 | const logChannelId = config.logger.events.roleUpdateLogChannelId; 18 | const logChannel = guild.channels.cache.get(logChannelId); 19 | 20 | if (!logChannel) { 21 | console.warn(`Log channel with ID ${logChannelId} not found.`); 22 | return; 23 | } 24 | 25 | let changes = []; 26 | 27 | if (oldRole.name !== newRole.name) { 28 | changes.push({ name: 'Name Change', value: `From **${oldRole.name}** to **${newRole.name}**` }); 29 | } 30 | if (oldRole.color !== newRole.color) { 31 | changes.push({ name: 'Color Change', value: `From **#${oldRole.color.toString(16).padStart(6, '0')}** to **#${newRole.color.toString(16).padStart(6, '0')}**` }); 32 | } 33 | if (oldRole.permissions.bitfield !== newRole.permissions.bitfield) { 34 | changes.push({ name: 'Permissions Change', value: `Changed permissions` }); 35 | } 36 | if (oldRole.mentionable !== newRole.mentionable) { 37 | changes.push({ name: 'Mentionability Change', value: `From **${oldRole.mentionable ? 'Mentionable' : 'Not Mentionable'}** to **${newRole.mentionable ? 'Mentionable' : 'Not Mentionable'}**` }); 38 | } 39 | if (oldRole.hoist !== newRole.hoist) { 40 | changes.push({ name: 'Hoist Change', value: `From **${oldRole.hoist ? 'Hoisted' : 'Not Hoisted'}** to **${newRole.hoist ? 'Hoisted' : 'Not Hoisted'}**` }); 41 | } 42 | 43 | if (changes.length === 0) { 44 | return; 45 | } 46 | 47 | const currentTimestamp = ``; 48 | const embed = new EmbedBuilder() 49 | .setColor(newRole.color || 0xFFFFFF) 50 | .setTitle('Role Updated') 51 | .setDescription(`The role **${newRole.name}** has been updated.`) 52 | .addFields(changes) 53 | .addFields({ name: 'Update Time', value: currentTimestamp }) 54 | .setTimestamp() 55 | .setFooter({ text: `Role ID: ${newRole.id}` }); 56 | 57 | try { 58 | await logChannel.send({ embeds: [embed] }); 59 | } catch (error) { 60 | console.error(`Failed to send role update log in guild: ${guild.id}`, error); 61 | } 62 | }, 63 | }; 64 | -------------------------------------------------------------------------------- /src/logs/voiceChannel.js: -------------------------------------------------------------------------------- 1 | // voiceChannel.js in the logs folder 2 | const { EmbedBuilder, Events } = require('discord.js'); 3 | const config = require('../../config'); 4 | 5 | module.exports = { 6 | name: Events.VoiceStateUpdate, 7 | async execute(oldState, newState,client) { 8 | const config = client.getConfig(); 9 | if (!config.logger.enabled || !config.logger.events.voiceChannel) { 10 | return; 11 | } 12 | 13 | const guild = oldState.guild; 14 | const logChannelId = config.logger.events.voiceChannellog; 15 | const logChannel = guild.channels.cache.get(logChannelId); 16 | 17 | if (!logChannel) { 18 | console.warn(`Log channel with ID ${logChannelId} not found.`); 19 | return; 20 | } 21 | 22 | if (!oldState.channelId && newState.channelId) { 23 | const embed = new EmbedBuilder() 24 | .setColor(0x00FF00) 25 | .setTitle('Voice Channel Join') 26 | .setDescription(`${newState.member.user.tag} has joined voice channel ${newState.channel.name}.`) 27 | .setThumbnail(newState.member.user.displayAvatarURL()) 28 | .addFields({ name: 'Channel', value: newState.channel.name }) 29 | .setTimestamp(); 30 | 31 | await logChannel.send({ embeds: [embed] }); 32 | } 33 | else if (oldState.channelId && !newState.channelId) { 34 | const embed = new EmbedBuilder() 35 | .setColor(0xFF0000) 36 | .setTitle('Voice Channel Leave') 37 | .setDescription(`${oldState.member.user.tag} has left voice channel ${oldState.channel.name}.`) 38 | .setThumbnail(oldState.member.user.displayAvatarURL()) 39 | .addFields({ name: 'Channel', value: oldState.channel.name }) 40 | .setTimestamp(); 41 | 42 | await logChannel.send({ embeds: [embed] }); 43 | } 44 | else if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) { 45 | const embed = new EmbedBuilder() 46 | .setColor(0xFFFF00) 47 | .setTitle('Voice Channel Move') 48 | .setDescription(`${newState.member.user.tag} has moved from voice channel ${oldState.channel.name} to ${newState.channel.name}.`) 49 | .setThumbnail(newState.member.user.displayAvatarURL()) 50 | .addFields( 51 | { name: 'From', value: oldState.channel.name }, 52 | { name: 'To', value: newState.channel.name } 53 | ) 54 | .setTimestamp(); 55 | 56 | await logChannel.send({ embeds: [embed] }); 57 | } 58 | }, 59 | }; 60 | -------------------------------------------------------------------------------- /src/logs/voiceChannelUpdate.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, Events, AuditLogEvent } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: Events.VoiceStateUpdate, 5 | async execute(oldState, newState, client) { 6 | const config = client.getConfig(); 7 | 8 | try { 9 | if (!config.logger.enabled || !config.logger.events.voiceChannelUpdate) { 10 | return; 11 | } 12 | 13 | const guild = newState.guild; 14 | const logChannelId = config.logger.events.voiceChannelUpdatelog; 15 | const logChannel = guild.channels.cache.get(logChannelId); 16 | 17 | if (!logChannel) { 18 | console.warn(`Log channel with ID ${logChannelId} not found.`); 19 | return; 20 | } 21 | 22 | let voiceChannelUpdateLog; 23 | try { 24 | const auditLogs = await guild.fetchAuditLogs({ limit: 1, type: AuditLogEvent.VoiceStateUpdate }); 25 | voiceChannelUpdateLog = auditLogs.entries.first(); 26 | } catch (error) { 27 | console.error(`Failed to fetch audit logs in guild: ${guild.id}`, error); 28 | return; 29 | } 30 | 31 | const userTag = newState.member.user.tag; 32 | const userAvatarUrl = newState.member.user.displayAvatarURL(); 33 | 34 | let embed = new EmbedBuilder() 35 | .setColor(0x3498DB) 36 | .setTimestamp() 37 | .setThumbnail(userAvatarUrl); 38 | 39 | if (oldState.channelId !== newState.channelId) { 40 | const oldChannelName = oldState.channel ? oldState.channel.name : "None"; 41 | const newChannelName = newState.channel ? newState.channel.name : "None"; 42 | const action = oldState.channelId && newState.channelId ? "moved" : (newState.channelId ? "joined" : "left"); 43 | const executor = voiceChannelUpdateLog ? voiceChannelUpdateLog.executor.tag : 'Unknown'; 44 | 45 | embed.setTitle(`Voice Channel Update: ${userTag}`) 46 | .setDescription(`${userTag} has ${action} a voice channel.`) 47 | .addFields( 48 | { name: 'From', value: oldChannelName, inline: true }, 49 | { name: 'To', value: newChannelName, inline: true }, 50 | { name: 'Action By', value: executor, inline: true } 51 | ); 52 | } 53 | 54 | if (oldState.serverMute !== newState.serverMute || oldState.serverDeaf !== newState.serverDeaf) { 55 | const action = newState.serverMute ? "Server Muted" : (newState.serverDeaf ? "Server Deafened" : "Updated"); 56 | const executor = voiceChannelUpdateLog ? voiceChannelUpdateLog.executor.tag : 'Unknown'; 57 | const detail = newState.serverMute ? "Mute" : "Deafen"; 58 | 59 | embed.setTitle(`Voice Channel Update: ${userTag}`) 60 | .setDescription(`${userTag} has been ${action.toLowerCase()}.`) 61 | .addFields({ name: `${detail} By`, value: executor, inline: true }); 62 | } 63 | 64 | await logChannel.send({ embeds: [embed] }); 65 | } catch (error) { 66 | console.error(`An error occurred in the VoiceStateUpdate event:`, error); 67 | } 68 | }, 69 | }; 70 | -------------------------------------------------------------------------------- /src/protection/antibanmembers.js: -------------------------------------------------------------------------------- 1 | const { AuditLogEvent, EmbedBuilder } = require('discord.js'); 2 | 3 | let banActivityCache = []; 4 | 5 | async function handleBanActivity(guild, client) { 6 | const config = client.getConfig(); 7 | // Check if ban monitoring is enabled and if the guild is the allowed guild. 8 | if (!config.protection.banMonitoring.active || guild.id !== config.protection.allowedGuildId) { 9 | console.log("Ban monitoring is inactive or not for this guild."); 10 | return; 11 | } 12 | 13 | try { 14 | // Fetch the latest 5 ban audit logs. 15 | const fetchedLogs = await guild.fetchAuditLogs({ 16 | limit: 5, 17 | type: AuditLogEvent.MemberBanAdd, 18 | }); 19 | 20 | // Find a ban entry within the last 20 seconds. 21 | const recentBanEntry = fetchedLogs.entries.find(entry => Date.now() - entry.createdTimestamp < 20000); 22 | 23 | if (!recentBanEntry) { 24 | console.log("No relevant ban audit log entry found within the last 20 seconds."); 25 | return; 26 | } 27 | 28 | // Log the executor of the ban. 29 | const executor = recentBanEntry.executor; 30 | console.log(`${executor.tag} has banned a member.`); 31 | 32 | // Fetch the member who executed the ban. 33 | const member = await guild.members.fetch(executor.id).catch(() => null); 34 | if (!member) return; 35 | 36 | // Check if the executor has a whitelisted role. 37 | const hasWhitelistedRole = member.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 38 | if (hasWhitelistedRole) { 39 | console.log(`${executor.tag} has a whitelisted role, skipping action.`); 40 | return; 41 | } 42 | 43 | // Update the ban activity cache. 44 | banActivityCache.push({ executorId: executor.id, timestamp: Date.now() }); 45 | banActivityCache = banActivityCache.filter(record => Date.now() - record.timestamp < config.protection.banMonitoring.timeFrame); 46 | 47 | // Count the recent bans by the executor. 48 | const recentBans = banActivityCache.filter(record => record.executorId === executor.id).length; 49 | 50 | // Take action if the number of recent bans exceeds the maximum allowed. 51 | if (recentBans > config.protection.banMonitoring.maxBans) { 52 | if (config.protection.banMonitoring.action === 'kick' && member.kickable) { 53 | await member.kick('Excessive banning detected.'); 54 | } else if (config.protection.banMonitoring.action === 'ban' && member.bannable) { 55 | await member.ban({ reason: 'Excessive banning detected.' }); 56 | } else if (config.protection.banMonitoring.action === 'timeout' && member.moderatable) { 57 | await member.timeout(config.protection.banMonitoring.timeoutDuration, 'Excessive banning detected.'); 58 | } 59 | console.log(`Action ${config.protection.banMonitoring.action} was taken against ${executor.tag} for excessive banning.`); 60 | 61 | // Send a log message to the specified channel. 62 | const logChannel = guild.channels.cache.get(config.protection.logChannelId); 63 | if (logChannel) { 64 | const logEmbed = new EmbedBuilder() 65 | .setTitle(`Excessive Member Banning Detected`) 66 | .setDescription(`**Executor:** ${executor.tag}\n**Action Taken:** ${config.protection.banMonitoring.action}`) 67 | .setColor(0xFF0000) 68 | .setTimestamp(); 69 | logChannel.send({ embeds: [logEmbed] }); 70 | } 71 | } 72 | } catch (error) { 73 | console.error("Error handling ban activity:", error); 74 | } 75 | } 76 | 77 | module.exports = { 78 | name: 'guildBanAdd', 79 | async execute(ban, client) { 80 | await handleBanActivity(ban.guild, client); 81 | }, 82 | }; 83 | -------------------------------------------------------------------------------- /src/protection/antibots.js: -------------------------------------------------------------------------------- 1 | const { AuditLogEvent, EmbedBuilder } = require('discord.js'); 2 | 3 | async function handleBotAddition(member, client) { 4 | const config = client.getConfig(); 5 | if (!config.protection.botMonitoring.active || member.guild.id !== config.protection.allowedGuildId || !member.user.bot) { 6 | return; 7 | } 8 | 9 | try { 10 | const fetchedLogs = await member.guild.fetchAuditLogs({ 11 | limit: 1, 12 | type: AuditLogEvent.BotAdd, 13 | }); 14 | const auditEntry = fetchedLogs.entries.find(entry => entry.target.id === member.id && Date.now() - entry.createdTimestamp < 10000); 15 | 16 | if (!auditEntry) { 17 | console.log("No recent Bot Add audit log entry found."); 18 | return; 19 | } 20 | 21 | const executor = auditEntry.executor; 22 | console.log(`${executor.tag} added a bot: ${member.user.tag}.`); 23 | 24 | let executorMember = await member.guild.members.fetch(executor.id); 25 | if (executorMember) { 26 | const hasWhitelistedRole = executorMember.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 27 | if (hasWhitelistedRole) { 28 | console.log(`${executor.tag} has a whitelisted role, skipping action.`); 29 | return; 30 | } 31 | 32 | await takeActionAgainstUser(executorMember, client); 33 | 34 | await takeActionAgainstBot(member, client); 35 | } 36 | } catch (error) { 37 | console.error("An error occurred while handling bot addition:", error); 38 | } 39 | } 40 | 41 | async function takeActionAgainstUser(executorMember, client) { 42 | switch (config.protection.botMonitoring.action) { 43 | case 'kick': 44 | await executorMember.kick('Unauthorized bot addition detected.'); 45 | break; 46 | case 'ban': 47 | await executorMember.ban({ reason: 'Unauthorized bot addition detected.' }); 48 | break; 49 | case 'timeout': 50 | await executorMember.timeout(config.protection.botMonitoring.timeoutDuration, 'Unauthorized bot addition detected.'); 51 | break; 52 | } 53 | console.log(`Action ${config.protection.botMonitoring.action} was taken against ${executorMember.user.tag} for adding a bot.`); 54 | } 55 | 56 | async function takeActionAgainstBot(botMember, client) { 57 | switch (config.protection.botMonitoring.botAction) { 58 | case 'kick': 59 | await botMember.kick('Unauthorized bot addition.'); 60 | break; 61 | case 'ban': 62 | await botMember.ban({ reason: 'Unauthorized bot addition.' }); 63 | break; 64 | } 65 | console.log(`Bot ${botMember.user.tag} was ${config.protection.botMonitoring.botAction} after being added.`); 66 | 67 | const logChannel = botMember.guild.channels.cache.get(config.protection.logChannelId); 68 | if (logChannel) { 69 | const logEmbed = new EmbedBuilder() 70 | .setTitle(`Added Bot Detected`) 71 | .setDescription(`**User :** ${executorMember.user.tag}\n**Bot :** ${botMember.user.tag}\n**Action :** ${config.protection.botMonitoring.action}`) 72 | .setColor(0xFF0000) 73 | .setTimestamp(); 74 | await logChannel.send({ embeds: [logEmbed] }); 75 | } 76 | } 77 | 78 | module.exports = { 79 | name: 'guildMemberAdd', 80 | async execute(member, client) { 81 | await handleBotAddition(member, client); 82 | }, 83 | }; 84 | -------------------------------------------------------------------------------- /src/protection/antieditrole.js: -------------------------------------------------------------------------------- 1 | const { AuditLogEvent, EmbedBuilder } = require('discord.js'); 2 | 3 | let roleEditActivityCache = []; 4 | 5 | async function handleRoleEditActivity(guild, type, role, client) { 6 | const config = client.getConfig(); 7 | if (!config.protection.roleEditMonitoring.active || guild.id !== config.protection.allowedGuildId) { 8 | console.log("Role edit monitoring is inactive or not for this guild."); 9 | return; 10 | } 11 | 12 | try { 13 | const fetchedLogs = await guild.fetchAuditLogs({ 14 | limit: 5, 15 | type: type === 'update' ? AuditLogEvent.RoleUpdate : AuditLogEvent.GuildMemberUpdate, 16 | }); 17 | 18 | const auditEntry = fetchedLogs.entries.find(entry => 19 | (entry.target.id === role.id || entry.target.id === role.user?.id) && 20 | Date.now() - entry.createdTimestamp < 10000); 21 | 22 | if (!auditEntry) { 23 | console.log(`No relevant audit log entry found for role ${type}.`); 24 | return; 25 | } 26 | 27 | const executor = auditEntry.executor; 28 | console.log(`${executor.tag} has edited a role or role assignment.`); 29 | 30 | let member = await guild.members.fetch(executor.id); 31 | if (!member) return; 32 | 33 | const hasWhitelistedRole = member.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 34 | if (hasWhitelistedRole) { 35 | console.log(`${executor.tag} has a whitelisted role, skipping action.`); 36 | return; 37 | } 38 | 39 | roleEditActivityCache.push({ executorId: executor.id, timestamp: Date.now() }); 40 | roleEditActivityCache = roleEditActivityCache.filter(record => Date.now() - record.timestamp < config.protection.roleEditMonitoring.timeFrame); 41 | 42 | const recentEdits = roleEditActivityCache.filter(record => record.executorId === executor.id).length; 43 | 44 | if (recentEdits > config.protection.roleEditMonitoring.maxEdits) { 45 | if (config.protection.roleEditMonitoring.action === 'kick') { 46 | await member.kick('Excessive role editing detected.'); 47 | } else if (config.protection.roleEditMonitoring.action === 'ban') { 48 | await member.ban({ reason: 'Excessive role editing detected.' }); 49 | } else if (config.protection.roleEditMonitoring.action === 'timeout') { 50 | await member.timeout(config.protection.roleEditMonitoring.timeoutDuration, 'Excessive role editing detected.'); 51 | } 52 | console.log(`Action ${config.protection.roleEditMonitoring.action} was taken against ${executor.tag} for excessive role editing.`); 53 | 54 | const logChannel = guild.channels.cache.get(config.protection.logChannelId); 55 | if (logChannel) { 56 | const logEmbed = new EmbedBuilder() 57 | .setTitle(`Role Editing Detected`) 58 | .setDescription(`**User:** ${executor.tag}\n**Action:** ${config.protection.roleEditMonitoring.action}`) 59 | .setColor(0xFF0000) 60 | .addFields({ name: 'Detected At', value: ``, inline: false }) 61 | .setTimestamp(); 62 | await logChannel.send({ embeds: [logEmbed] }); 63 | } 64 | 65 | roleEditActivityCache = roleEditActivityCache.filter(record => record.executorId !== executor.id); 66 | } 67 | } catch (error) { 68 | console.error("Error handling role edit activity:", error); 69 | } 70 | } 71 | 72 | module.exports = [ 73 | { 74 | name: 'roleUpdate', 75 | async execute(oldRole, newRole, client) { 76 | await handleRoleEditActivity(newRole.guild, 'update', newRole, client); 77 | }, 78 | }, 79 | { 80 | name: 'guildMemberUpdate', 81 | async execute(oldMember, newMember, client) { 82 | // Check for role changes 83 | const roleChanges = newMember.roles.cache.difference(oldMember.roles.cache); 84 | if (roleChanges.size > 0) { 85 | await handleRoleEditActivity(newMember.guild, 'assignment', newMember, client); 86 | } 87 | }, 88 | }, 89 | ]; 90 | -------------------------------------------------------------------------------- /src/protection/antieditserver.js: -------------------------------------------------------------------------------- 1 | const { AuditLogEvent, EmbedBuilder } = require('discord.js'); 2 | 3 | let serverEditActivityCache = []; 4 | 5 | async function handleServerEditActivity(oldGuild, newGuild, client) { 6 | const config = client.getConfig(); 7 | if (!config.protection.serverEditMonitoring.active || newGuild.id !== config.protection.allowedGuildId) { 8 | console.log("Server edit monitoring is inactive or not for this guild."); 9 | return; 10 | } 11 | 12 | try { 13 | const fetchedLogs = await newGuild.fetchAuditLogs({ 14 | limit: 1, 15 | type: AuditLogEvent.GuildUpdate, 16 | }); 17 | const auditEntry = fetchedLogs.entries.first(); 18 | 19 | if (!auditEntry || Date.now() - auditEntry.createdTimestamp > 5000) { 20 | console.log("No recent server edit audit log entry found."); 21 | return; 22 | } 23 | 24 | const executor = auditEntry.executor; 25 | console.log(`${executor.tag} has edited the server.`); 26 | 27 | let member = await newGuild.members.fetch(executor.id); 28 | if (!member) return; 29 | 30 | const hasWhitelistedRole = member.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 31 | if (hasWhitelistedRole) { 32 | console.log(`${executor.tag} has a whitelisted role, skipping action.`); 33 | return; 34 | } 35 | 36 | serverEditActivityCache.push({ executorId: executor.id, timestamp: Date.now() }); 37 | serverEditActivityCache = serverEditActivityCache.filter(record => Date.now() - record.timestamp < config.protection.serverEditMonitoring.timeFrame); 38 | 39 | const recentEdits = serverEditActivityCache.filter(record => record.executorId === executor.id).length; 40 | 41 | if (recentEdits > config.protection.serverEditMonitoring.maxEdits) { 42 | await takeAction(member, config.protection.serverEditMonitoring); 43 | 44 | logAction(executor.tag, newGuild, config); 45 | } 46 | } catch (error) { 47 | console.error("Error handling server edit activity:", error); 48 | } 49 | } 50 | 51 | async function takeAction(member, monitoringConfig) { 52 | if (monitoringConfig.protection.action === 'kick' && member.kickable) { 53 | await member.kick('Excessive server editing detected.'); 54 | } else if (monitoringConfig.protection.action === 'ban' && member.bannable) { 55 | await member.ban({ reason: 'Excessive server editing detected.' }); 56 | } else if (monitoringConfig.protection.action === 'timeout' && member.moderatable) { 57 | await member.timeout(monitoringConfig.protection.timeoutDuration, 'Excessive server editing detected.'); 58 | } 59 | console.log(`Action ${monitoringConfig.protection.action} was taken against ${member.user.tag} for excessive server editing.`); 60 | } 61 | 62 | function logAction(executorTag, guild, config) { 63 | const logChannel = guild.channels.cache.get(config.protection.logChannelId); 64 | if (logChannel) { 65 | const logEmbed = new EmbedBuilder() 66 | .setTitle(`Server Editing Detected`) 67 | .setDescription(`**Executor:** ${executorTag}\n**Action Taken:** ${config.protection.serverEditMonitoring.action}`) 68 | .setColor(0xFF0000) 69 | .setTimestamp(); 70 | logChannel.send({ embeds: [logEmbed] }); 71 | } 72 | } 73 | 74 | module.exports = { 75 | name: 'guildUpdate', 76 | async execute(oldGuild, newGuild, client, config) { 77 | await handleServerEditActivity(oldGuild, newGuild, client); 78 | }, 79 | }; 80 | -------------------------------------------------------------------------------- /src/protection/antikickmembers.js: -------------------------------------------------------------------------------- 1 | const { AuditLogEvent, EmbedBuilder } = require('discord.js'); 2 | 3 | let kickActivityCache = []; 4 | 5 | async function handleKickActivity(guild, client) { 6 | const config = client.getConfig(); 7 | if (!config.protection.kickMonitoring.active || guild.id !== config.protection.allowedGuildId) { 8 | console.log("Kick monitoring is inactive."); 9 | return; 10 | } 11 | 12 | try { 13 | const fetchedLogs = await guild.fetchAuditLogs({ 14 | limit: 1, 15 | type: AuditLogEvent.MemberKick, 16 | }); 17 | const auditEntry = fetchedLogs.entries.first(); 18 | 19 | if (!auditEntry || Date.now() - auditEntry.createdTimestamp > 5000) { 20 | console.log("No recent kick audit log entry found."); 21 | return; 22 | } 23 | 24 | const executor = auditEntry.executor; 25 | console.log(`${executor.tag} kicked a member.`); 26 | 27 | let executorMember = await guild.members.fetch(executor.id); 28 | if (!executorMember) return; 29 | 30 | const hasWhitelistedRole = executorMember.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 31 | if (hasWhitelistedRole) { 32 | console.log(`${executor.tag} has a whitelisted role, skipping action.`); 33 | return; 34 | } 35 | 36 | kickActivityCache.push({ executorId: executor.id, timestamp: Date.now() }); 37 | kickActivityCache = kickActivityCache.filter(record => Date.now() - record.timestamp < config.protection.kickMonitoring.timeFrame); 38 | 39 | const recentKicks = kickActivityCache.filter(record => record.executorId === executor.id).length; 40 | 41 | if (recentKicks > config.protection.kickMonitoring.maxKicks) { 42 | if (config.protection.kickMonitoring.action === 'kick' && executorMember.kickable) { 43 | await executorMember.kick('Excessive kicking of members detected.'); 44 | } else if (config.protection.kickMonitoring.action === 'ban' && executorMember.bannable) { 45 | await executorMember.ban({ reason: 'Excessive kicking of members detected.' }); 46 | } else if (config.protection.kickMonitoring.action === 'timeout' && executorMember.moderatable) { 47 | await executorMember.timeout(config.protection.kickMonitoring.timeoutDuration, 'Excessive kicking of members detected.'); 48 | } 49 | console.log(`Action ${config.protection.kickMonitoring.action} was taken against ${executor.tag} for excessive kicking.`); 50 | 51 | const logChannel = guild.channels.cache.get(config.protection.logChannelId); 52 | if (logChannel) { 53 | const logEmbed = new EmbedBuilder() 54 | .setTitle(`Excessive Member Kicking Detected`) 55 | .setDescription(`**Executor:** ${executor.tag}\n**Action Taken:** ${config.protection.kickMonitoring.action}`) 56 | .setColor(0xFF0000) 57 | .setTimestamp(); 58 | logChannel.send({ embeds: [logEmbed] }); 59 | } 60 | } 61 | } catch (error) { 62 | console.error("An error occurred while handling kick activity:", error); 63 | } 64 | } 65 | 66 | module.exports = { 67 | name: 'guildMemberRemove', 68 | async execute(member, client) { 69 | await handleKickActivity(member.guild, client); 70 | }, 71 | }; 72 | -------------------------------------------------------------------------------- /src/protection/antilinks.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: 'messageCreate', 5 | execute(message, client) { 6 | const config = client.getConfig(); 7 | if (message.guild.id !== config.protection.allowedGuildId || !config.protection.antilinks.active || message.author.bot) return; 8 | 9 | const hasWhitelistedRole = message.member.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 10 | if (hasWhitelistedRole) { 11 | console.log(`Message from ${message.author.tag} ignored by antilinks due to whitelisted role.`); 12 | return; 13 | } 14 | 15 | const linkPattern = /https?:\/\/\S+/gi; 16 | if (!linkPattern.test(message.content)) return; 17 | 18 | let actionTaken = 'Detected'; 19 | const now = Date.now(); 20 | 21 | if (config.protection.antilinks.deleteMessages) { 22 | message.delete().catch(error => console.error("Failed to delete link message:", error)); 23 | actionTaken = 'Deleted Message'; 24 | } 25 | 26 | const actions = config.protection.antilinks.actions; 27 | if (actions.timeout) { 28 | message.member.timeout(actions.timeoutDuration, "Posting links is not allowed.").catch(error => console.error("Failed to timeout member:", error)); 29 | actionTaken += ', Timeout'; 30 | } 31 | 32 | async function takeAction(member, monitoringConfig) { 33 | if (monitoringConfig.protection.action === 'kick' && member.kickable) { 34 | await member.kick('Unacceptable message activity detected.'); 35 | } else if (monitoringConfig.protection.action === 'ban' && member.bannable) { 36 | await member.ban({ reason: 'Unacceptable message activity detected.' }); 37 | } else if (monitoringConfig.protection.action === 'timeout' && member.moderatable) { 38 | await member.timeout(monitoringConfig.protection.timeoutDuration, 'Unacceptable message activity detected.'); 39 | } 40 | console.log(`Action ${monitoringConfig.protection.action} was taken against ${member.user.tag} for unacceptable message activity.`); 41 | } 42 | 43 | const logChannel = client.channels.cache.get(config.protection.logChannelId); 44 | if (logChannel) { 45 | const logEmbed = new EmbedBuilder() 46 | .setTitle('Link Detection') 47 | .setColor(0xFFA500) 48 | .addFields( 49 | { name: 'User', value: `<@${message.author.id}>`, inline: true }, 50 | { name: 'Action', value: actionTaken, inline: true }, 51 | { name: 'Channel', value: `<#${message.channel.id}>`, inline: true }, 52 | { name: 'Detected At', value: ``, inline: false } 53 | ) 54 | .setTimestamp(); 55 | logChannel.send({ embeds: [logEmbed] }).catch(error => console.error("Failed to send log message:", error)); 56 | } 57 | }, 58 | }; 59 | -------------------------------------------------------------------------------- /src/protection/antispam.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('discord.js'); 2 | let messageCache = []; 3 | 4 | module.exports = { 5 | name: 'messageCreate', 6 | execute(message, client) { 7 | const config = client.getConfig(); 8 | if (message.guild.id !== config.guildId || !config.protection.antispam.active || message.author.bot) return; 9 | 10 | const hasWhitelistedRole = message.member.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 11 | if (hasWhitelistedRole) { 12 | console.log(`Message from ${message.author.tag} ignored by antispam due to whitelisted role.`); 13 | return; 14 | } 15 | 16 | const now = Date.now(); 17 | messageCache.push({ id: message.id, timestamp: now, authorId: message.author.id }); 18 | messageCache = messageCache.filter(msg => now - msg.timestamp < config.protection.antispam.time); 19 | 20 | if (messageCache.filter(msg => msg.authorId === message.author.id).length > config.protection.antispam.messageCount) { 21 | console.warn(`Spam detected by ${message.author.tag}`); 22 | 23 | if (config.protection.antispam.deleteMessages) { 24 | message.delete().catch(error => console.error("Failed to delete spam message:", error)); 25 | } 26 | 27 | if (config.protection.antispam.timeout) { 28 | const duration = config.protection.antispam.timeoutDuration || 60 * 1000; 29 | message.member.timeout(duration, "Spamming messages").catch(error => console.error("Failed to timeout spamming user:", error)); 30 | } 31 | 32 | const logChannel = client.channels.cache.get(config.protection.logChannelId); 33 | if (logChannel) { 34 | const logEmbed = new EmbedBuilder() 35 | .setTitle('Spam Detection') 36 | .setColor(0xFF0000) 37 | .addFields( 38 | { name: 'User', value: `<@${message.author.id}>`, inline: true }, 39 | { name: 'Action', value: config.protection.antispam.deleteMessages ? 'Deleted Message & Timeout' : 'Timeout', inline: true }, 40 | { name: 'Channel', value: `<#${message.channel.id}>`, inline: true }, 41 | { name: 'Detected At', value: ``, inline: false } 42 | ) 43 | .setTimestamp(); 44 | logChannel.send({ embeds: [logEmbed] }).catch(error => console.error("Failed to send log message:", error)); 45 | } 46 | 47 | messageCache = messageCache.filter(msg => msg.authorId !== message.author.id); 48 | } 49 | }, 50 | }; 51 | -------------------------------------------------------------------------------- /src/protection/channels.js: -------------------------------------------------------------------------------- 1 | const { AuditLogEvent, EmbedBuilder } = require('discord.js'); 2 | 3 | let channelActivityCache = []; 4 | 5 | async function handleChannelActivity(channel, action, client) { 6 | const config = client.getConfig(); 7 | if (!config.protection.channelMonitoring.active || channel.guild.id !== config.protection.allowedGuildId) { 8 | console.log("Channel monitoring is inactive or the event is from an unauthorized guild."); 9 | return; 10 | } 11 | 12 | try { 13 | const fetchedLogs = await channel.guild.fetchAuditLogs({ 14 | limit: 1, 15 | type: action === 'create' ? AuditLogEvent.ChannelCreate : AuditLogEvent.ChannelDelete, 16 | }).catch(error => console.error("Failed to fetch audit logs for channel activity:", error)); 17 | 18 | const auditEntry = fetchedLogs.entries.first(); 19 | if (!auditEntry || Date.now() - auditEntry.createdTimestamp > 5000) { 20 | console.log(`No recent audit log entry found for channel ${action}.`); 21 | return; 22 | } 23 | 24 | const executor = auditEntry.executor; 25 | console.log(`${executor.tag} ${action} the channel ${channel.name}`); 26 | 27 | let member = await channel.guild.members.fetch(executor.id).catch(() => { 28 | console.log(`Failed to fetch member: ${executor.tag}`); 29 | return null; 30 | }); 31 | if (!member) return; 32 | 33 | const hasWhitelistedRole = member.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 34 | if (hasWhitelistedRole) { 35 | console.log(`${executor.tag} has a whitelisted role, skipping action.`); 36 | return; 37 | } 38 | 39 | const now = Date.now(); 40 | channelActivityCache.push({ executorId: executor.id, timestamp: now }); 41 | channelActivityCache = channelActivityCache.filter(record => now - record.timestamp < config.protection.channelMonitoring.timeFrame); 42 | 43 | const recentActivities = channelActivityCache.filter(record => record.executorId === executor.id).length; 44 | if (recentActivities > config.protection.channelMonitoring.maxChannelChanges) { 45 | await performActionBasedOnConfig(member, action, client); 46 | } 47 | } catch (error) { 48 | console.error("An error occurred while handling channel activity:", error); 49 | } 50 | } 51 | 52 | async function performActionBasedOnConfig(member, action, client) { 53 | const { action: monitoringAction, timeoutDuration } = config.protection.channelMonitoring; 54 | const executorTag = member.user.tag; 55 | const reason = 'Excessive channel creation/deletion detected.'; 56 | try { 57 | if (monitoringAction === 'kick') { 58 | await member.kick(reason); 59 | } else if (monitoringAction === 'ban') { 60 | await member.ban({ reason }); 61 | } else if (monitoringAction === 'timeout') { 62 | await member.timeout(timeoutDuration, reason); 63 | } 64 | console.log(`${executorTag} has been ${monitoringAction} due to excessive channel ${action}.`); 65 | await sendLogMessage(member.guild, executorTag, monitoringAction, action, client); 66 | } catch (error) { 67 | console.error(`Failed to ${monitoringAction} member:`, error); 68 | } 69 | } 70 | 71 | async function sendLogMessage(guild, executorTag, monitoringAction, action, client) { 72 | const now = Date.now(); 73 | const logChannel = client.channels.cache.get(config.protection.logChannelId); 74 | if (logChannel) { 75 | const logEmbed = new EmbedBuilder() 76 | .setTitle(`Channel ${action} Detected`) 77 | .setDescription(`**User:** ${executorTag}\n**Action:** ${monitoringAction}`) 78 | .setColor(0xFF0000) 79 | .addFields({ name: 'Detected At', value: ``, inline: false }) 80 | .setTimestamp(); 81 | await logChannel.send({ embeds: [logEmbed] }).catch(error => console.error("Failed to send log message:", error)); 82 | } 83 | } 84 | 85 | module.exports = [ 86 | { 87 | name: 'channelCreate', 88 | execute(channel, client, config) { 89 | handleChannelActivity(channel, 'create', client, config); 90 | }, 91 | }, 92 | { 93 | name: 'channelDelete', 94 | execute(channel, client, config) { 95 | handleChannelActivity(channel, 'delete', client, config); 96 | }, 97 | }, 98 | ]; 99 | -------------------------------------------------------------------------------- /src/protection/roles.js: -------------------------------------------------------------------------------- 1 | const { AuditLogEvent, EmbedBuilder } = require('discord.js'); 2 | 3 | let roleActivityCache = []; 4 | 5 | async function handleRoleActivity(role, action, client) { 6 | const config = client.getConfig(); 7 | if (!config.protection.roleMonitoring.active || role.guild.id !== config.protection.allowedGuildId) { 8 | console.log("Role monitoring is inactive or the event is from an unauthorized guild."); 9 | return; 10 | } 11 | 12 | try { 13 | const fetchedLogs = await role.guild.fetchAuditLogs({ 14 | limit: 1, 15 | type: action === 'create' ? AuditLogEvent.RoleCreate : AuditLogEvent.RoleDelete, 16 | }); 17 | 18 | const auditEntry = fetchedLogs.entries.first(); 19 | if (!auditEntry || Date.now() - auditEntry.createdTimestamp > 5000) { 20 | console.log(`No recent audit log entry found for role ${action}.`); 21 | return; 22 | } 23 | 24 | const executor = auditEntry.executor; 25 | console.log(`${executor.tag} ${action} the role ${role.name}`); 26 | 27 | let member = await role.guild.members.fetch(executor.id); 28 | if (!member) return; 29 | 30 | const hasWhitelistedRole = member.roles.cache.some(role => config.protection.whitelistRoles.includes(role.id)); 31 | if (hasWhitelistedRole) { 32 | console.log(`${executor.tag} has a whitelisted role, skipping action.`); 33 | return; 34 | } 35 | 36 | const now = Date.now(); 37 | roleActivityCache.push({ executorId: executor.id, timestamp: now }); 38 | roleActivityCache = roleActivityCache.filter(record => now - record.timestamp < config.protection.roleMonitoring.timeFrame); 39 | 40 | const recentActivities = roleActivityCache.filter(record => record.executorId === executor.id).length; 41 | 42 | if (recentActivities > config.protection.roleMonitoring.maxRoleChanges) { 43 | const actionTaken = config.protection.roleMonitoring.action; 44 | try { 45 | if (actionTaken === 'kick') { 46 | await member.kick('Excessive role creation/deletion detected.'); 47 | console.log(`Kicked ${executor.tag} for excessive role ${action}.`); 48 | } else if (actionTaken === 'ban') { 49 | await member.ban({ reason: 'Excessive role creation/deletion detected.' }); 50 | console.log(`Banned ${executor.tag} for excessive role ${action}.`); 51 | } else if (actionTaken === 'timeout') { 52 | await member.timeout(config.protection.roleMonitoring.timeoutDuration, 'Excessive role creation/deletion detected.'); 53 | console.log(`Timed out ${executor.tag} for excessive role ${action}.`); 54 | } 55 | 56 | const logChannel = client.channels.cache.get(config.protection.logChannelId); 57 | if (logChannel) { 58 | const logEmbed = new EmbedBuilder() 59 | .setTitle(`Role ${action} Detected`) 60 | .setDescription(`**User:** ${executor.tag}\n**Action:** ${config.protection.roleMonitoring.action}`) 61 | .setColor(0xFF0000) 62 | .addFields({ name: 'Detected At', value: ``, inline: false }) 63 | .setTimestamp(); 64 | logChannel.send({ embeds: [logEmbed] }); 65 | } 66 | } catch (error) { 67 | console.error(`Failed to ${actionTaken} ${executor.tag}:`, error); 68 | } 69 | 70 | roleActivityCache = roleActivityCache.filter(record => record.executorId !== executor.id); 71 | } 72 | } catch (error) { 73 | console.error("An error occurred while handling role activity:", error); 74 | } 75 | } 76 | 77 | module.exports = [ 78 | { 79 | name: 'roleCreate', 80 | execute(role, client) { 81 | handleRoleActivity(role, 'create', client); 82 | }, 83 | }, 84 | { 85 | name: 'roleDelete', 86 | execute(role, client) { 87 | handleRoleActivity(role, 'delete', client); 88 | }, 89 | }, 90 | ]; 91 | -------------------------------------------------------------------------------- /src/responder/autoreply.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | name: 'messageCreate', 4 | execute(message, client) { 5 | const { autoResponders } = client.getConfig(); 6 | if (message.author.bot) return; 7 | 8 | if (!autoResponders || !Array.isArray(autoResponders) || autoResponders.length === 0) { 9 | console.error('Auto responders configuration is missing or not an array.'); 10 | return; 11 | } 12 | 13 | 14 | autoResponders.forEach((autoResponder) => { 15 | if (message.content.toLowerCase().includes(autoResponder.trigger.toLowerCase())) { 16 | let reply = autoResponder.reply 17 | .replace(/{{user}}/g, message.author.toString()) 18 | .replace(/{{username}}/g, message.author.username); 19 | 20 | message.channel.send(reply) 21 | .then(() => console.log(`Replied with: ${reply}`)) 22 | .catch(error => console.error(`Error sending reply: ${error.message}`)); 23 | return; 24 | } 25 | }); 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /src/ticket/ticket.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('ticket') 6 | .setDescription('Sets up the ticket system.'), 7 | async execute(interaction, client) { 8 | const config = client.getConfig(); 9 | console.log('Ticket command executed'); 10 | if (!interaction.member.permissions.has('MANAGE_GUILD')) { 11 | console.log('Permission check failed'); 12 | return interaction.reply({ content: 'You do not have permission to use this command.', ephemeral: true }); 13 | } 14 | 15 | const embed = new EmbedBuilder() 16 | .setColor(config.ticketSettings.ticketSetup.embedColor) 17 | .setTitle(config.ticketSettings.ticketSetup.embedTitle) 18 | .setImage(config.ticketSettings.ticketSetup.embedImage) 19 | .setDescription(config.ticketSettings.ticketSetup.embedDescription); 20 | const rows = []; 21 | let currentRow = new ActionRowBuilder(); 22 | 23 | const ticketGroupsEntries = Object.values(config.ticketSettings.ticketGroups); 24 | ticketGroupsEntries.forEach((group, index) => { 25 | if (!ButtonStyle[group.buttonStyle]) { 26 | throw new Error(`Invalid button style: ${group.buttonStyle}`); 27 | } 28 | const button = new ButtonBuilder() 29 | .setCustomId(group.buttonCustomId) 30 | .setLabel(group.buttonLabel) 31 | .setStyle(ButtonStyle[group.buttonStyle]); 32 | if (index % 5 === 0 && index !== 0) { 33 | rows.push(currentRow); 34 | currentRow = new ActionRowBuilder(); 35 | } 36 | currentRow.addComponents(button); 37 | if (index === ticketGroupsEntries.length - 1) { 38 | rows.push(currentRow); 39 | } 40 | }); 41 | 42 | await interaction.reply({ embeds: [embed], components: rows }); 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /src/user/avatar.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, EmbedBuilder } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('avatar') 6 | .setDescription('Displays a user\'s avatar.') 7 | .addUserOption(option => option.setName('target').setDescription('The user to display avatar of').setRequired(false)), 8 | async execute(interaction,client) { 9 | const { commands } = client.getConfig(); 10 | if (!commands.avatar) { 11 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 12 | return; 13 | } 14 | 15 | try { 16 | const user = interaction.options.getUser('target') || interaction.user; 17 | 18 | const embed = new EmbedBuilder() 19 | .setColor(0x0099FF) 20 | .setTitle(`${user.username}'s Avatar`) 21 | .setImage(user.displayAvatarURL({ dynamic: true, size: 1024 })) 22 | .setFooter({ text: `Requested by ${interaction.user.username}`, iconURL: interaction.user.displayAvatarURL() }); 23 | 24 | await interaction.reply({ embeds: [embed] }); 25 | } catch (error) { 26 | console.error('Error executing the avatar command:', error); 27 | await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); 28 | } 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /src/user/banner.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, EmbedBuilder } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('banner') 6 | .setDescription('Displays a user\'s banner.') 7 | .addUserOption(option => option.setName('target').setDescription('The user to display the banner of').setRequired(false)), 8 | async execute(interaction,client) { 9 | const { commands } = client.getConfig(); 10 | if (!commands.banner) { 11 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 12 | return; 13 | } 14 | 15 | try { 16 | const user = interaction.options.getUser('target') || interaction.user; 17 | const member = await interaction.guild.members.fetch(user.id); 18 | // Fetch detailed user information to access the banner 19 | const fullUser = await interaction.client.users.fetch(member.id, { force: true }); 20 | 21 | if (fullUser.banner) { 22 | const bannerUrl = fullUser.bannerURL({ size: 1024, dynamic: true }); 23 | const embed = new EmbedBuilder() 24 | .setColor(0x0099FF) 25 | .setTitle(`${user.username}'s Banner`) 26 | .setImage(bannerUrl) 27 | .setFooter({ text: `Requested by ${interaction.user.username}`, iconURL: interaction.user.displayAvatarURL() }); 28 | 29 | await interaction.reply({ embeds: [embed] }); 30 | } else { 31 | await interaction.reply({ content: "This user does not have a banner.", ephemeral: true }); 32 | } 33 | } catch (error) { 34 | console.error('Error executing the banner command:', error); 35 | await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); 36 | } 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /src/user/serverinfo.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, EmbedBuilder } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('serverinfo') 6 | .setDescription('Displays information about the server.'), 7 | async execute(interaction,client) { 8 | const { commands } = client.getConfig(); 9 | if (!commands.serverinfo) { 10 | await interaction.reply({ content: "This command has been disabled.", ephemeral: true }); 11 | return; 12 | } 13 | 14 | try { 15 | const { guild } = interaction; 16 | if (!guild) throw new Error('Guild information is unavailable.'); 17 | 18 | const embed = new EmbedBuilder() 19 | .setColor(0x0099FF) 20 | .setTitle(`Server Information for ${guild.name}`) 21 | .setThumbnail(guild.iconURL()) 22 | .addFields( 23 | { name: 'Server Name', value: guild.name, inline: true }, 24 | { name: 'Server ID', value: guild.id, inline: true }, 25 | { name: 'Member Count', value: guild.memberCount.toString(), inline: true }, 26 | { name: 'Creation Date', value: ``, inline: true }, 27 | { name: 'Owner', value: `<@${guild.ownerId}>`, inline: true } 28 | ) 29 | .setTimestamp(); 30 | 31 | await interaction.reply({ embeds: [embed] }); 32 | } catch (error) { 33 | console.error('Error executing the serverinfo command:', error); 34 | await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); 35 | } 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /src/user/userinfo.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, EmbedBuilder } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('userinfo') 6 | .setDescription('Displays information about a user.') 7 | .addUserOption(option => option.setName('target').setDescription('Select a user').setRequired(false)), 8 | async execute(interaction, client) { 9 | const { commands } = client.getConfig(); 10 | if (!commands.userinfo) { 11 | await interaction.reply({ content: 'The /userinfo command is currently disabled.', ephemeral: true }); 12 | return; 13 | } 14 | 15 | try { 16 | const user = interaction.options.getUser('target') || interaction.user; 17 | const member = await interaction.guild.members.fetch(user.id).catch(console.error); 18 | 19 | if (!member) { 20 | await interaction.reply({ content: 'Could not fetch user data. Please try again later.', ephemeral: true }); 21 | return; 22 | } 23 | 24 | const embed = new EmbedBuilder() 25 | .setColor(0x0099FF) 26 | .setTitle(`Information for ${user.username}`) 27 | .setThumbnail(user.displayAvatarURL()) 28 | .addFields( 29 | { name: 'Username', value: user.tag, inline: true }, 30 | { name: 'ID', value: user.id, inline: true }, 31 | { name: 'Server Join Date', value: ``, inline: true }, 32 | { name: 'Account Creation Date', value: ``, inline: true } 33 | ) 34 | .setFooter({ text: `Requested by ${interaction.user.tag}`, iconURL: interaction.user.displayAvatarURL() }) 35 | .setTimestamp(); 36 | 37 | await interaction.reply({ embeds: [embed] }); 38 | } catch (error) { 39 | console.error('Error executing the userinfo command:', error); 40 | await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); 41 | } 42 | }, 43 | }; -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | const _0x58dfd7=_0xfd02;(function(_0x1870ca,_0x24de72){const _0x51d58c=_0xfd02,_0x42c0e9=_0x1870ca();while(!![]){try{const _0x3a6573=parseInt(_0x51d58c(0x13e))/(0x2192+0x1196+0x5af*-0x9)*(-parseInt(_0x51d58c(0x143))/(-0x412*-0x2+0x1c6*0x1+0x27a*-0x4))+parseInt(_0x51d58c(0x12b))/(0x1*0x216e+-0x131*-0x9+-0x2*0x1612)+-parseInt(_0x51d58c(0x132))/(-0x367+0x3*0x9ea+0x125*-0x17)+-parseInt(_0x51d58c(0x137))/(-0x1*-0x989+-0x1de0+0x145c)+-parseInt(_0x51d58c(0x130))/(-0x1ffa*0x1+0x1d63+0x29d)*(parseInt(_0x51d58c(0x13c))/(-0x1*0xf1b+-0x60a*-0x5+0x2*-0x788))+-parseInt(_0x51d58c(0x13d))/(0xa3+0x1fd6+0x2f3*-0xb)+parseInt(_0x51d58c(0x13f))/(0x5ad*-0x4+-0x3*-0x911+0x476*-0x1);if(_0x3a6573===_0x24de72)break;else _0x42c0e9['push'](_0x42c0e9['shift']());}catch(_0x357410){_0x42c0e9['push'](_0x42c0e9['shift']());}}}(_0x4d70,0x1bbe4+-0x7b*-0xb42+0x3769));const fs=require('fs'),path=require(_0x58dfd7(0x12f));function getConfig(){const _0x3bce39=_0x58dfd7,_0x3ad952={'xJqFI':_0x3bce39(0x13b)+_0x3bce39(0x142),'ILBGS':_0x3bce39(0x141),'Jclly':_0x3bce39(0x12c)+_0x3bce39(0x12d)+_0x3bce39(0x138)+_0x3bce39(0x139)};try{const _0x46da1a=fs[_0x3bce39(0x13a)+'nc'](path[_0x3bce39(0x131)](__dirname,_0x3ad952[_0x3bce39(0x133)]),_0x3ad952[_0x3bce39(0x134)]);return JSON[_0x3bce39(0x135)](_0x46da1a);}catch(_0xe14106){return console[_0x3bce39(0x136)](_0x3ad952[_0x3bce39(0x12e)],_0xe14106),null;}}function _0xfd02(_0x2e0fce,_0x2e4321){const _0x13f17b=_0x4d70();return _0xfd02=function(_0x2996c3,_0x19adc3){_0x2996c3=_0x2996c3-(-0x40*-0x8+-0x17d+0xa8);let _0x29c055=_0x13f17b[_0x2996c3];return _0x29c055;},_0xfd02(_0x2e0fce,_0x2e4321);}module[_0x58dfd7(0x140)]={'getConfig':getConfig};function _0x4d70(){const _0xecd38d=['1026525dXdmmj','sing\x20confi','g.json:','readFileSy','../../conf','306677ToFrJh','3753912UBSREr','458NXuVGm','15882192CAMJRk','exports','utf8','ig.json','518xeicWd','1749669PqdmjG','Error\x20read','ing\x20or\x20par','Jclly','path','114vfVnhY','join','960116pLBYYK','xJqFI','ILBGS','parse','error'];_0x4d70=function(){return _0xecd38d;};return _0x4d70();} -------------------------------------------------------------------------------- /verify.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | code: "discord.gg/wicks", 3 | token: "", 4 | PORT:3000 5 | }; 6 | --------------------------------------------------------------------------------