Compare commits

...
327 Commits
Author SHA1 Message Date
1tzEmerald 81bda67ae4 Merge pull request #172 from Emerald-Services/1tzemerald-patch-3
Update supportbot.yml
2024-07-30 17:58:41 +01:00
1tzEmerald 25bbd1ff85 Update supportbot.yml 2024-07-30 17:58:01 +01:00
1tzEmerald 164d695a5f Merge pull request #171 from Emerald-Services/1tzemerald-patch-2
Create 0000000000000000.json
2024-07-30 17:57:33 +01:00
1tzEmerald 57e4a3e77c Create 0000000000000000.json 2024-07-30 17:57:12 +01:00
1tzEmerald a6ac532b2b Merge pull request #169 from Emerald-Services/dev
8.0.1 Dev -> Release Branch
2024-07-30 17:47:13 +01:00
1tzEmerald 4f14722e14 8.0.1 Update 2024-07-30 17:45:35 +01:00
1tzEmerald 9a6eece7a1 v8.1 2024-07-09 22:49:49 +01:00
1tzEmerald fd65d0a9a7 8.1-BETA 2024-07-03 13:46:57 +01:00
ItsNyoty 48500fe8a4 Update README.md 2024-07-03 13:42:46 +02:00
1tzEmerald 8d8d9e4bee 8.0.1 Bug Fix 2024-06-13 18:01:41 +01:00
1tzEmerald dcbddf9f23 8.0.1 - Bug Fix 2024-06-13 17:36:44 +01:00
1tzEmerald 7449c0a61a License files 2024-06-12 12:55:45 +01:00
1tzEmerald c95b8ccb32 SupportBot 8.0 2024-06-12 12:54:31 +01:00
1tzEmerald 2c5bfe8e33 Merge pull request #135 from ItsNyoty/patch-1
Update messages.yml
2022-09-05 13:42:52 +01:00
ItsNyoty a3bbd97333 Update messages.yml
TicketExists wasn't defined before
2022-08-29 14:58:01 +02:00
1tzEmerald 4ea488951d Delete oldconfig.yml 2022-08-12 01:38:07 +01:00
1tzEmerald 481424d5a6 Update LICENSE.md 2022-08-12 01:37:49 +01:00
1tzEmerald fe82e96cc1 Update LICENSE.md 2022-08-12 01:37:31 +01:00
1tzEmerald 976258c959 Delete .gitignore 2022-08-12 01:37:14 +01:00
1tzEmerald 83cf0689e2 Delete .DS_Store 2022-08-12 01:37:00 +01:00
ItzEmerald c911cb4423 v8.0 New configuration files 2022-08-12 01:35:36 +01:00
ItzEmerald 4eadef8b65 8.0 Dev 1.2
Reworked configuration files & completed upgrade to V14
2022-08-11 19:19:29 +01:00
ItzEmerald 4e081358ff v8.0-Dev-1.1 2022-07-23 07:50:12 +01:00
ItzEmerald 209ec0b435 v8.0 - Dev-1 2022-07-22 13:19:05 +01:00
Xiled Emerald 6d363abb54 Merge pull request #129 from SypherRed/dev
Better looking readme
2022-07-01 22:19:03 +01:00
SypherRed 6f8b84aeda Update README.md 2022-07-01 23:16:16 +02:00
SypherRed 5b8c5da33a Update README.md 2022-07-01 23:14:01 +02:00
Xiled Emerald b6ef0f95cb Merge pull request #126 from SypherRed/release
Muted Role check and issue fix
2022-06-30 15:49:14 +01:00
SypherRed cce1480a42 remove empty declaration
AboutMe was removed in a previous version.
2022-06-29 13:12:56 +02:00
ItzEmerald 44fbe9f2d6 FINAL 7.7 2022-06-28 03:15:52 +01:00
ItzEmerald 29db6c7d67 7.7 FINAL BETA 2022-06-28 03:14:54 +01:00
SypherRed 26e9b56961 Issue fix with Muted Role check
Fixed the issue to recognize a Muted Role and made changes to ready.js accordingly
2022-06-27 19:03:34 +02:00
SypherRed 979271cfb5 beta push of muted check
push of a check if author has a muted role on ticket opening, if so, decline the interaction

Also either check for missing role or not
2022-06-23 20:58:03 +02:00
ItzEmerald 69f0b00ed3 7.7 2022-06-23 00:05:08 +01:00
ItzEmerald c1a1839457 7.7 BETA 3 2022-06-22 23:30:59 +01:00
Xiled Emerald dd4b53800e Merge pull request #124 from Emerald-Services/add-license-1
Create LICENSE.md
2022-06-22 23:05:38 +01:00
Xiled Emerald 1fc94528fc Merge pull request #123 from SypherRed/release
embed fix and updates
2022-06-22 23:05:25 +01:00
SypherRed bb1a817980 fix previous push of embed
fixed the if-statement of embed
2022-06-22 20:59:45 +02:00
SypherRed 53305acbc7 Fixed embed command
Added a check if the field options are used, if not leave it ignored and don't add some.

This was fixed due to ticket-0038.
2022-06-22 18:21:25 +02:00
Xiled Emerald d0f1bae0bd Create LICENSE.md 2022-06-22 02:24:19 +01:00
SypherRed c0cf3b1bb7 Update several files
* added to .gitignore ".DS_Store"

* changed commented head in "suggest.js" and "translate.js"

* Removed "AboutMe" due it to being unfunctional and can be set in the Developer Portal

* Removed the icon in "ticket-panel.yml"

* Updated dependencies and changed version to match current
2022-06-21 09:54:22 +02:00
Xiled Emerald ce67b668d5 Update Client.js 2022-06-21 01:42:59 +01:00
Xiled Emerald 3273cfd0e1 Update help.js 2022-06-21 01:41:53 +01:00
Xiled Emerald fd992a6514 Update supportbot.yml 2022-06-21 01:41:17 +01:00
Xiled Emerald 550d681fe1 Merge pull request #122 from RandomTomato/release
Added 3 new settings in supportbot.yml for more customization
2022-06-21 01:39:35 +01:00
ItzEmerald 7d29226953 BETA 2 - V7.7 2022-06-21 01:38:22 +01:00
BuildTools 38da72ca91 Added 3 new settings in supportbot.yml for more customization 2022-06-18 11:19:12 +09:30
Xiled Emerald eab11361cb Update ticket-panel-id.json 2022-06-16 22:30:13 +01:00
Xiled Emerald b281bba36f Merge pull request #120 from Emerald-Services/beta
7.6 Release
2022-06-16 22:26:50 +01:00
ItzEmerald 5e38573aed 7.6 2022-06-16 22:12:14 +01:00
ItzEmerald da7b6d487c 7.6-Pre1
Whats New?
  - Ability to add as many departments as you need (Don't go to crazy 😂 )
  - Merged Sypher's Translate & UserInfo Addon into Features

------------

  - Add a role automatically when a user joins the server
  - Announce a welcome message with full cusomtization
  - Announce a leave message with full cusomtization
  - Added "ephermal" to majority messages.

Install modules use - npm install
2022-06-16 02:31:58 +01:00
Xiled Emerald 6bf4e5f4bb Update README.md 2022-06-14 23:02:12 +01:00
Xiled Emerald 213f532a3c Merge pull request #114 from Emerald-Services/dev
7.5 push
2022-02-27 04:37:24 +00:00
ItzEmerald 45bd88e4d2 7.5 commit 2022-02-27 04:30:15 +00:00
Xiled Emerald 4eb8658459 Update supportbot.yml 2022-02-27 00:39:36 +00:00
Noah b37118fee2 Fix addon handler 2022-02-25 21:57:54 -06:00
Noah 026caba68a Fix setFooters 2022-02-25 21:55:33 -06:00
Noah 2003f8801a Fixed ticket perms 2022-02-25 21:51:22 -06:00
Noah 473bacf13a Removed Guild 2022-02-17 19:57:37 -06:00
Noah 8b3f2bc61a Fix missing user or subuser 2022-02-17 19:57:11 -06:00
Noah 3aa373c33c fix bad code 2022-02-11 23:47:06 -06:00
Noah 9b6263e583 Fix DM help menu 2022-02-11 23:41:02 -06:00
Noah 3e066d08ce New Departments 2022-02-11 23:34:38 -06:00
Noah aa48e28162 Fix Typos 2022-02-04 20:00:31 -06:00
Noah dc660ed94a Bug Fixes 2022-02-04 17:56:11 -06:00
Noah e02ecf9553 Bug fixes 2022-02-04 17:55:02 -06:00
Noah 23acc0926f Fix BitField Error 2022-02-04 17:49:02 -06:00
Xiled Emerald 3fc1cd18d5 Merge pull request #109 from Emerald-Services/dev
7.4.2 Pull Request
2022-02-03 17:26:54 +00:00
Noah ebe29b403e Prettier 2022-01-30 00:07:04 -06:00
Noah dcba3312dd Misc 2022-01-29 23:57:10 -06:00
Noah 7fddeeec37 Change Max to 100 2022-01-10 17:48:31 -06:00
Noah b5341b023f Fix embed command 2021-12-29 10:20:29 -06:00
Noah bbb7443ef2 Fix suggest command 2021-12-28 19:06:35 -06:00
Noah 22df347bb9 Merge pull request #108 from astranger1k/dev
Updated Documentation URLs + Added invite URL to log upon launch.
2021-12-23 09:18:47 -06:00
Kieran Davies 9aed6b8f35 Updated Documentation URLs + Added invite URL to log upon launch. 2021-12-23 11:48:51 +00:00
Noah 9e7ec9f1bd 7.4.2 2021-12-19 13:06:32 -06:00
Noah 373f43eac5 Channel can now be id or name 2021-12-19 13:03:33 -06:00
Noah 6c91b2791a Fix users can't send messages 2021-12-19 13:02:43 -06:00
Noah bde62a431f Merge branch 'dev' into release 2021-12-18 22:59:41 -06:00
Noah 615a074540 move filter 2021-12-18 22:59:05 -06:00
Noah 09b335ac46 Update ticket.js 2021-12-18 22:42:51 -06:00
Noah 2701880c77 Merge pull request #106 from Emerald-Services/dev
v7.4.1 Release
2021-12-18 22:37:29 -06:00
Noah 24c8f2fb38 v7.4.1 2021-12-18 22:28:08 -06:00
Noah c3ec158ac3 Fix id 2021-12-18 22:23:18 -06:00
Noah b3690222d0 Fixed id 2021-12-18 22:18:05 -06:00
Noah 4d7583785b Fixed ticket id 2021-12-18 22:14:11 -06:00
Noah 17ad1a15db Delete .DS_Store 2021-12-18 21:32:21 -06:00
Noah 4c89de9e76 Merge pull request #103 from Emerald-Services/dev
v7.4 Release
2021-12-18 21:31:56 -06:00
Noah 5f25af41f9 Merge branch 'release' into dev 2021-12-18 21:30:53 -06:00
Noah 3a3ee357fc Update packages 2021-12-18 21:17:06 -06:00
Noah 08a6d27903 Change to ephemeral 2021-12-18 20:56:30 -06:00
Noah 33f7675aac Added Max Ticket Count + Timeout 2021-12-18 20:54:01 -06:00
Noah 1178a0a611 Add StaffOnly close option 2021-12-18 19:39:59 -06:00
Noah 96ded77bec Fixed perms bug 2021-12-18 19:24:39 -06:00
Noah e83ca8cb2b add guild 2021-12-18 18:58:02 -06:00
Noah e507176d39 New addon handler 2021-12-18 18:57:45 -06:00
Noah 4e554b8bee rename slashCommandOptions to options, and permission to permissions 2021-12-18 18:57:26 -06:00
Noah bc649caa99 remove unused code 2021-12-18 18:56:25 -06:00
Noah f7a4c7b616 rename var + remove unused code 2021-12-18 18:56:02 -06:00
Noah 2c7be5882c Added getRole, getChannel, getCategory functions 2021-12-15 00:19:40 -06:00
Noah 6107d268f7 Fixed close + Send transcript to subusers 2021-12-14 18:04:38 -06:00
Noah 7760699155 Update node.js.yml 2021-12-04 21:30:48 -06:00
Noah acf349c72e Fix test mode 2021-12-04 21:26:55 -06:00
Noah 8096e5b882 Add npm test 2021-12-04 21:25:02 -06:00
Noah 873cfc7dc2 Merge branch 'dev' of https://github.com/Emerald-Services/SupportBot into dev 2021-12-04 21:22:10 -06:00
Noah 038174bc7e temp 2021-12-04 21:22:08 -06:00
Noah 14881096bb Update node.js.yml 2021-12-04 21:22:07 -06:00
Noah ed1905d8f4 Added test mode 2021-12-04 21:19:51 -06:00
Noah 72c0a2efa3 Update node.js.yml 2021-12-04 21:07:27 -06:00
Noah e599d48713 Update node.js.yml 2021-12-04 21:05:36 -06:00
Noah 7f44634d4f Delete prettier.yml 2021-12-04 21:04:47 -06:00
Noah 44170caac6 Update supportbot.yml 2021-12-04 21:01:34 -06:00
Noah adedfadd92 Prettier 2021-12-04 20:58:19 -06:00
Noah 6b01d0c8fe Possibly fix /close? 2021-12-04 20:57:23 -06:00
Noah d4d96f59ab Update 2021-12-04 20:25:49 -06:00
Noah a1bf7ed6bd Fix syntax 2021-12-04 20:25:35 -06:00
Noah 306e20efc9 Merge pull request #99 from DarkerInker/patch-1
wrong way to send embeds
2021-12-04 20:21:07 -06:00
Noah f593f6e0a8 Update close.js 2021-12-04 20:20:55 -06:00
DarkerInker 74646a4318 wrong way to send embeds
You are using the old way to send embeds. I'm not sure how you forgot about this one area but everyone makes mistakes :D
2021-12-02 13:52:07 -06:00
Noah 8bfcba8832 Merge pull request #97 from SypherRed/dev
fixed help command
2021-11-28 23:35:31 -06:00
SypherRed 4ba5621a4d Merge branch 'dev' into dev 2021-11-28 14:55:48 +01:00
N0ahMC 1f928324c2 Prettified Code! 2021-11-26 19:18:15 +00:00
Noah 3771872cd2 Update prettier.yml 2021-11-26 13:17:57 -06:00
Noah f359a60343 Update node.js.yml 2021-11-26 13:16:15 -06:00
Noah f53afd7bc9 Create prettier.yml 2021-11-26 13:13:15 -06:00
Noah e7dcc2ab29 Update help.js 2021-11-26 12:56:21 -06:00
SypherRed 0118b9e591 fixed help command 2021-11-25 01:51:56 +01:00
Noah ffe42f9777 Update ticket.js 2021-11-24 18:14:07 -06:00
Noah 5a467599e9 Update hello.js 2021-11-24 00:15:16 -06:00
Noah c56e78484a Update dependencies 2021-11-23 20:29:22 -06:00
Noah 1ee0d4a09e Update close.js 2021-11-23 18:09:06 -06:00
Noah ffdce5820b Fix close button 2021-11-23 18:08:45 -06:00
Noah 9fed504f37 Fixed /close 2021-11-23 17:37:25 -06:00
Noah 6c5799be0d Fix ID 2021-11-23 17:32:57 -06:00
Noah b6747a0340 Made warning ephemeral 2021-11-23 16:51:28 -06:00
Noah cd6df02e30 Changed TicketLog_Title 2021-11-23 15:50:56 -06:00
Noah edbef6a36f Fixed close command 2021-11-23 15:49:37 -06:00
Noah b6a0016f5f Changed TicketData Structure 2021-11-23 15:48:45 -06:00
Noah e740c17837 Update package-lock.json 2021-11-21 18:42:24 -06:00
Noah 7eb949f109 Better finds 2021-11-21 18:42:18 -06:00
Noah 02394e310d Exit if joins or leaves guild 2021-11-17 19:04:38 -06:00
Noah ef83832819 Added missing role and channel check 2021-11-17 19:04:20 -06:00
Noah a82101ab30 Register commands in Guild 2021-11-17 19:03:35 -06:00
Noah 007c78930e Added Guild to config 2021-11-17 19:03:11 -06:00
Noah 300c83512c Fixed token, and changed version for future 2021-11-11 17:18:30 -06:00
Noah b674872c56 Fixed Archive Bug 2021-11-10 21:41:12 -06:00
Noah 12a7680275 Fix spelling 2021-11-10 21:23:07 -06:00
Noah c9cf7c942b Prettier 2021-11-10 21:22:08 -06:00
Noah 8e0326c8f8 Removed HelpMenu 2021-11-10 21:21:50 -06:00
Noah 13972119a8 Update package-lock.json 2021-11-10 21:21:05 -06:00
Noah acf165a119 Add Button Emoji 2021-11-10 21:18:49 -06:00
Xiled Emerald bdff7c6069 Update supportbot.yml 2021-11-07 21:39:53 +00:00
Xiled Emerald e2e3376c87 Merge pull request #91 from Emerald-Services/dev
Dev
2021-10-29 23:38:32 +01:00
Xiled Emerald 3c613088e5 Delete supportbot.yml 2021-10-29 23:38:18 +01:00
Xiled Emerald 7e9ece50a0 Update issue templates 2021-10-29 22:40:12 +01:00
Xiled Emerald af81b6536a Update issue templates 2021-10-29 22:38:13 +01:00
ItzEmerald 4cd3ecf81f 7.3 2021-10-29 19:12:11 +01:00
Noah 31f6b9e08e Fix suggestions 2021-10-28 19:08:06 -05:00
Noah 02de920cb3 Update package.json 2021-10-28 18:39:06 -05:00
Noah 84c0905297 Update version numbers 2021-10-28 18:07:43 -05:00
Noah 250583f859 Delete commands directory 2021-10-28 18:04:26 -05:00
Noah ee7d42196d Create remove.js 2021-10-28 18:03:51 -05:00
Noah a397de2b9f Create close.js 2021-10-28 18:03:27 -05:00
Noah 0610df9400 Create add.js 2021-10-28 18:03:06 -05:00
Noah ed583deb31 Updated css 2021-10-27 20:44:10 -05:00
Noah e039048fc6 Updated role defaults 2021-10-27 20:24:26 -05:00
Noah f2ea9650c4 Renamed file 2021-10-27 20:24:10 -05:00
Noah 1e89057006 Added font 2021-10-27 20:19:33 -05:00
Noah 019bb4842f Fixed bug 2021-10-27 20:19:27 -05:00
Noah 4cb45beded Fixed bug 2021-10-27 20:18:06 -05:00
Noah 8a2059f087 Fixed suggest command bug 2021-10-27 20:05:45 -05:00
Noah a6b105a2e1 Updated config defaults 2021-10-27 19:48:00 -05:00
Noah 6c14a6a06c Rename 2021-10-27 19:39:07 -05:00
Noah cddd5d0026 Moved configs from Data to Configs 2021-10-27 19:30:10 -05:00
Noah 78dea91e1d Prettier 2021-10-27 19:20:10 -05:00
Xiled Emerald 3df591ec52 Update supportbot.yml 2021-10-25 23:19:07 +01:00
Xiled Emerald 1c4032caa6 Create suggest.js 2021-10-25 23:18:28 +01:00
Noah 465c422171 Update README.md 2021-10-25 00:16:00 -05:00
Noah 284e8dc6f5 Fixed spelling 2021-10-25 00:15:54 -05:00
Noah 3fc905c82e Update supportbot.yml 2021-10-25 00:03:28 -05:00
Noah 55a42b88ae Ran prettier 2021-10-25 00:02:23 -05:00
Noah bd26162e4a Fixed bug 2021-10-25 00:02:17 -05:00
Xiled Emerald 62e7e33406 Update Client.js 2021-10-25 00:13:27 +01:00
Xiled Emerald 2f0ddcec3f Merge pull request #77 from 1tzemerald/SupportBot-BETA
SupportBot 7.1 merge to main branch
2021-10-24 22:56:37 +01:00
Xiled Emerald 7cdfa68e0e Delete supportbot-config.yml 2021-10-24 22:56:14 +01:00
Xiled Emerald f8939a964d Delete .DS_Store 2021-10-24 22:54:15 +01:00
Xiled Emerald 7830e5dda5 Add files via upload 2021-10-24 22:48:25 +01:00
Xiled Emerald 6aa2f22294 Create ready.js 2021-10-24 22:47:42 +01:00
Xiled Emerald 50b14e3d44 Add files via upload 2021-10-24 22:46:36 +01:00
Xiled Emerald e09c2192c2 Delete events directory 2021-10-24 22:45:44 +01:00
Xiled Emerald b725d2cc62 Delete messageReactionAdd.js 2021-10-24 22:44:51 +01:00
Xiled Emerald abf3f617a4 Delete ticket.js 2021-10-24 22:44:29 +01:00
Xiled Emerald 1eda7e66fe Delete ping.js 2021-10-24 22:44:11 +01:00
ItzEmerald b5000531c4 Merge branch 'SupportBot-BETA' of https://github.com/1tzemerald/SupportBot into SupportBot-BETA 2021-10-24 22:42:49 +01:00
ItzEmerald d4f95e752b SupportBot-7.2-Release 2021-10-24 22:41:46 +01:00
Noah e31c611f70 Removed prefix 2021-10-23 20:17:58 -05:00
Noah 085481bee6 Spelling Mistakes 2021-10-23 20:15:07 -05:00
Noah cf610fbe49 Ran prettier 2021-10-23 20:12:04 -05:00
Noah b681eb3cd2 Create .gitignore 2021-10-23 20:10:49 -05:00
Noah f8ffdf0e81 Delete node_modules 2021-10-23 20:10:16 -05:00
Noah ba38bce1da Updated structures 2021-10-23 20:09:15 -05:00
Noah 3a39b05fe4 Updated packages 2021-10-23 20:08:55 -05:00
Noah 27d2982b28 Removed text commands 2021-10-23 20:07:37 -05:00
Noah 33e4d97be5 Updated for slash commands 2021-10-23 20:04:02 -05:00
Xiled Emerald 654064d7c5 Create messageReactionAdd.js 2021-10-23 22:44:59 +01:00
Noah aeb0da9e0d Removed console.log 2021-10-23 16:26:07 -05:00
Noah cb1a2fe067 Fixed Slash commands 2021-10-23 16:23:02 -05:00
ItzEmerald 85667ddfad 7.2 pre-3 2021-10-21 19:28:23 +01:00
Alexersion 7ad5016966 Unneeded workspace updates removed. 2021-10-13 11:12:08 -04:00
ItzEmerald 45c3315fd0 Update .DS_Store 2021-10-07 20:46:20 +01:00
ItzEmerald c5f550dd00 Pre-2 2021-10-07 20:46:18 +01:00
ItzEmerald 37c870c7ab SupportBot Pre-7.2
SupportBot Build for DiscordJS 13
2021-10-04 20:41:05 +01:00
Xiled Emerald 155b768f73 Update supportbot-config.yml 2021-10-04 13:56:30 +01:00
ItzEmerald 09f0873f27 SupportBot 7.3 2021-10-04 13:54:30 +01:00
ItzEmerald 19a12f6c8f SupportBot 7.2 2021-09-11 15:29:21 +01:00
Xiled Emerald 79a498d1d6 Update transcript.js 2021-08-07 16:19:13 +01:00
ItzEmerald 12a03c36f3 SupportBot 7.1 Release
Features all-new ticket system with new reaction technology enabling you to delete & lock tickets with one-click!
2021-08-06 16:34:15 +01:00
ItzEmerald ddc8bcab9b Pre-2 2021-08-05 13:40:19 +01:00
ItzEmerald 35dacfd48a Merge branch 'master' of https://github.com/1tzemerald/SupportBot 2021-08-05 13:39:48 +01:00
ItzEmerald 611cef34ab 7.1-Pre-2 2021-08-05 13:39:44 +01:00
Xiled Emerald 8a8f9fe890 Update SupportTickets.json 2021-08-05 01:07:16 +01:00
Xiled Emerald 5a65b70c80 Update ticketreaction.yml 2021-08-05 01:07:04 +01:00
Xiled Emerald 8bea3faa1f Update TicketID.json 2021-08-05 01:06:53 +01:00
ItzEmerald 4125954d53 7.1 Pre-1
Revamp of ticket system
2021-08-05 01:03:58 +01:00
Xiled Emerald 3d9c5a729e Create SupportBot_ENG.yml 2021-08-01 16:21:47 +01:00
Xiled Emerald 51d775ea6d Delete supportbot-config_GER.yml 2021-08-01 16:20:25 +01:00
Xiled Emerald e461c47c4b Delete supportbot-config_FR.yml 2021-08-01 16:20:19 +01:00
Xiled Emerald bbdb38e45a Delete supportbot-config_ES.yml 2021-07-31 15:33:37 +01:00
Xiled Emerald 083e047aec Delete supportbot-config_ENG.yml 2021-07-31 15:33:30 +01:00
Xiled Emerald 84e0b504ab Delete .DS_Store 2021-06-30 21:33:35 +01:00
Xiled Emerald bedff6832c Update supportbot-config.yml 2021-06-30 21:33:16 +01:00
ItzEmerald 6c29e04de2 7.0 2021-06-30 21:30:41 +01:00
ItzEmerald ba674323e1 Update help.js 2021-06-15 21:05:38 +01:00
ItzEmerald 6d756a161e Update help.js 2021-06-15 21:04:32 +01:00
ItzEmerald 66a5cd95ec Update README.md 2021-06-15 19:56:39 +01:00
ItzEmerald 9f70648264 Update suggest.js 2021-06-15 19:10:17 +01:00
ItzEmerald b975b79691 Update removeUser.js 2021-06-15 19:10:07 +01:00
ItzEmerald 3cab896954 Update purge.js 2021-06-15 19:09:58 +01:00
ItzEmerald b9680e5b35 Update ping.js 2021-06-15 19:09:46 +01:00
ItzEmerald 43a003ca7d Update newticket.js 2021-06-15 19:09:35 +01:00
ItzEmerald fbe1cf2009 Update links.js 2021-06-15 19:09:23 +01:00
ItzEmerald fdee61cc11 Update kick.js 2021-06-15 19:09:06 +01:00
ItzEmerald 8b51200d9c Update help.js 2021-06-15 19:08:56 +01:00
ItzEmerald 0631ab536a Update close.js 2021-06-15 19:08:46 +01:00
ItzEmerald 0d76e76519 Update botSay.js 2021-06-15 19:07:42 +01:00
ItzEmerald 9e9f83d211 Update blacklistUser.js 2021-06-15 19:07:26 +01:00
ItzEmerald 0829d477d9 Update ban.js 2021-06-15 19:07:10 +01:00
ItzEmerald 1b7109fa23 Update announce.js 2021-06-15 19:06:58 +01:00
ItzEmerald 366669ccd8 Update addUser.js 2021-06-15 19:06:40 +01:00
ItzEmerald e05edd89fa Update ready.js 2021-06-15 18:09:24 +01:00
ItzEmerald a405df66c9 Update message.js 2021-06-15 18:09:06 +01:00
ItzEmerald 28a57ead9f Update index.js 2021-06-15 18:08:32 +01:00
ItzEmerald 72bfacae75 Merge pull request #68 from DuAnti7423/master
Boolean Changes, help menu fix, raw Event, ID Support added
2021-05-24 12:48:25 +01:00
DuAnti7423 10f8821b3b Random Stuff
idk why github thinks i changed something
2021-05-23 10:45:00 +02:00
DuAnti7423 92a3745ce1 Update supportbot-config.yml
Added HelpMenu_WithKey Option.
Boolean Changes
2021-05-23 10:44:00 +02:00
DuAnti7423 aff7ff1451 Update ready.js
ID Support, Boolean Changes
2021-05-23 10:41:15 +02:00
DuAnti7423 9e63e0ff09 Create raw.js
Added Raw-Event, probably fixxed the ticketreaction isnt 100% workin
2021-05-23 10:41:05 +02:00
DuAnti7423 2c5ebd8620 Update messageReactionAdd.js
ID Support, Boolean Changes
2021-05-23 10:40:37 +02:00
DuAnti7423 e6d63db3a9 Update guildMemberRemove.js
ID Support, Boolean Changes
2021-05-23 10:40:32 +02:00
DuAnti7423 2cc316aafb Update guildMemberAdd.js
ID Support, Boolean Changes
2021-05-23 10:40:28 +02:00
DuAnti7423 4f25cfa0dd Update suggest.js
ID Support, Boolean Changes
2021-05-23 10:40:20 +02:00
DuAnti7423 0385de3882 Update removeUser.js
ID Support, Boolean Changes
2021-05-23 10:40:16 +02:00
DuAnti7423 2e1253c54e Update purge.js
ID Support, Boolean Changes
2021-05-23 10:40:10 +02:00
DuAnti7423 14df15caeb Update ping.js
ID Support, Boolean Changes
2021-05-23 10:40:03 +02:00
DuAnti7423 af481a2ec8 Update newticket.js
ID Support, Boolean Changes

Fixxed everyone permissions on ticket creation
2021-05-23 10:39:58 +02:00
DuAnti7423 96c1d80844 Update links.js
ID Support, Boolean Changes
2021-05-23 10:39:42 +02:00
DuAnti7423 57ea2e25bd Update kick.js
ID Support, Boolean Changes
2021-05-23 10:39:36 +02:00
DuAnti7423 cd17b0a6d7 Update help.js
ID Support, Boolean Changes
2021-05-23 10:39:31 +02:00
DuAnti7423 c5dd8823f6 Update close.js
ID Support, Boolean Changes
2021-05-23 10:39:24 +02:00
DuAnti7423 c27f16f753 Update botSay.js
ID Support, Boolean Changes
2021-05-23 10:39:18 +02:00
DuAnti7423 4842610229 Update blacklistUser.js
ID Support, Boolean Changes
2021-05-23 10:39:13 +02:00
DuAnti7423 bd33669dba Update ban.js
ID Support, Boolean Changes
2021-05-23 10:39:08 +02:00
DuAnti7423 e81684d322 Update announce.js
ID Support, Boolean Changes
2021-05-23 10:39:03 +02:00
DuAnti7423 8209dfa26c Update addUser.js
ID Support, Boolean Changes
2021-05-23 10:38:55 +02:00
DuAnti7423 0a82c62a4e boolean changes
workin on suggestion #67  from pat2381
2021-05-22 23:41:39 +02:00
DuAnti7423 4399dfe6b8 Fixxed a copy error
replaced reactionUser with user cause reactionUser was defined in the ticket command
2021-05-22 23:38:32 +02:00
DuAnti7423 defd0cc78c Merge branch 'master' of https://github.com/DuAnti7423/SupportBot 2021-05-22 23:13:25 +02:00
DuAnti7423 fd5fc8294c update help.js
Fixxed a bug with staffcommands show
2021-05-22 23:13:16 +02:00
ItzEmerald 10823b416c Update package.json 2021-05-14 15:46:23 +01:00
ItzEmerald 4490920ac6 Update index.js 2021-05-14 15:46:08 +01:00
ItzEmerald e0b8ad4a32 Update supportbot-config.yml 2021-05-14 15:45:49 +01:00
ItzEmerald e11063832b Merge pull request #65 from DuAnti7423/master
Blacklist Command
2021-05-12 15:35:56 +01:00
DuAnti7423 d598fdd753 updated help.js 2021-05-09 00:25:30 +02:00
DuAnti7423 157b93239a Added Logging to Blacklist 2021-05-08 23:55:57 +02:00
DuAnti7423 3d7058dccd Merge branch 'master' of https://github.com/DuAnti7423/SupportBot 2021-05-08 23:44:12 +02:00
DuAnti7423 1ec654d1ea Blacklist Command
Added Blacklist Command
Added configoption
2021-05-08 23:42:35 +02:00
ItzEmerald 8ce2d4269d Merge pull request #62 from DuAnti7423/master
Blacklist Role
2021-05-07 15:09:46 +01:00
DuAnti7423 49e8aa7869 Blacklist Role
Added Blacklist Role, via ID or Name
2021-04-17 22:15:59 +02:00
ItzEmerald 0827f55d43 Update guildMemberAdd.js 2021-03-31 01:21:34 +01:00
ItzEmerald ba6ff8c342 Update node.js.yml 2021-03-31 00:28:35 +01:00
ItzEmerald c0b7dc2737 Create node.js.yml 2021-03-31 00:27:10 +01:00
ItzEmerald ab6abd453b Delete node_modules directory 2021-03-30 20:20:33 +01:00
ItzEmerald 77921aca75 Update ready.js 2021-03-30 20:18:37 +01:00
ItzEmerald a8f91c4814 Update messageReactionAdd.js 2021-03-30 20:12:29 +01:00
ItzEmerald 7780fa792c Updated 2021-03-27 16:58:27 +00:00
ItzEmerald 41e4c376ec Merge branch 'master' of https://github.com/1tzemerald/SupportBot 2021-03-27 16:22:37 +00:00
ItzEmerald 09aad61cfe SB-6.3-BETA 2
Added Moderation
Added Node Modules
2021-03-27 16:22:19 +00:00
ItzEmerald 31ac81428f Update ready.js 2021-03-24 20:56:57 +00:00
ItzEmerald 60daab82d2 Merge branch 'master' of https://github.com/1tzemerald/SupportBot 2021-03-24 16:26:21 +00:00
ItzEmerald e7a0544004 Added Image to ReactionPanel 2021-03-24 16:25:16 +00:00
ItzEmerald ff0364bba8 Update supportbot-config_FR.yml 2021-03-17 16:04:41 +00:00
ItzEmerald a3b64be351 Update supportbot-config_ES.yml 2021-03-17 16:03:52 +00:00
ItzEmerald eae370e346 Update README.md 2021-03-17 14:36:11 +00:00
ItzEmerald 0d86b50a83 Update supportbot-config_ENG.yml 2021-03-17 14:35:45 +00:00
ItzEmerald 543b9028a3 Update supportbot-config_ES.yml 2021-03-17 14:35:15 +00:00
ItzEmerald 867f12d11f Update supportbot-config_FR.yml 2021-03-17 14:33:13 +00:00
ItzEmerald 462781ea6a Update supportbot-config_GER.yml 2021-03-17 14:31:37 +00:00
ItzEmerald c300ab6459 Update supportbot-config.yml 2021-03-11 18:57:27 +00:00
ItzEmerald 448d8f3007 Update ready.js 2021-03-11 18:55:33 +00:00
ItzEmerald faa53b0af1 Create supportbot-config_ENG.yml 2021-03-03 19:42:29 +00:00
ItzEmerald 8e53b8d9a6 Rename supportbot-config_GN.yml to supportbot-config_GER.yml 2021-03-03 19:41:36 +00:00
ItzEmerald 5678567baa Create supportbot-config_GN.yml 2021-03-03 19:37:39 +00:00
ItzEmerald 1c30f73bb1 Create supportbot-config_FR.yml 2021-03-03 18:36:02 +00:00
ItzEmerald bd3dbc3033 Rename supportbot-config.y_ES.yml to supportbot-config_ES.yml 2021-03-03 00:39:41 +00:00
ItzEmerald 3c312ab8d3 Create supportbot-config.y_ES.yml
Spanish
2021-03-03 00:39:20 +00:00
ItzEmerald 7284785db0 Delete eyeroe.md 2021-02-13 16:25:53 +00:00
ItzEmerald 4e543ea490 Update messageReactionAdd.js 2021-02-13 16:25:28 +00:00
ItzEmerald 4d3540126f Update eyeroe.md 2021-02-08 15:34:02 +00:00
ItzEmerald 6c29f0d792 Create eyeroe.md 2021-02-08 15:33:44 +00:00
wxip c85df7c40f Update ready.js 2021-02-05 21:39:16 +02:00
wxip 4f6ff575ce Quick Fix
Hopefully fixes `INVALID_TYPE` error on GuildMemberAdd event.
2021-02-05 21:26:21 +02:00
ItzEmerald aaf3890f71 Update guildMemberAdd.js 2021-02-05 16:15:51 +00:00
ItzEmerald 4f9837d991 Merge branch 'master' of https://github.com/1tzemerald/SupportBot 2021-02-04 12:54:29 +00:00
ItzEmerald 2e2eb008c6 Language PRE-01 2021-02-04 12:54:19 +00:00
ItzEmerald fa7074bb59 Update messageReactionAdd.js 2021-02-02 17:56:13 +00:00
ItzEmerald 18a7def050 Delete package-lock.json 2021-02-02 17:55:00 +00:00
ItzEmerald 40e9cf5fe5 Update messageReactionAdd.js 2021-02-02 17:52:07 +00:00
69 changed files with 5973 additions and 2186 deletions

No files matched your search

+26
View File
@@ -0,0 +1,26 @@
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require("js-yaml");
const { Command } = require('../Structures/Addon.js'); // Adjust the path as needed
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
module.exports = new Command({
name: "addon",
description: "This is a sample addon!",
options: [],
permissions: ["Administrator"],
async run(interaction) {
let disableCommand = true;
const PingEmbed = new Discord.EmbedBuilder()
.setDescription(
`This is a sample addon.\n\nPong! \`${interaction.client.ws.ping} ms\``
)
.setColor(supportbot.Embed.Colours.General);
interaction.reply({
embeds: [PingEmbed],
});
},
});
+128
View File
@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
our discord.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
+92
View File
@@ -0,0 +1,92 @@
# Contributing
When contributing to this repository, please first discuss the change you wish to make via issue,
email, or any other method with the owners of this repository before making a change.
Please note we have a code of conduct, please follow it in all your interactions with the project.
## Pull Request Process
1. Ensure any install or build dependencies are removed before the end of the layer when doing a
build.
2. Update the README.md with details of changes to the interface, this includes new environment
variables, exposed ports, useful file locations and container parameters.
3. Increase the version numbers in any examples files and the README.md to the new version that this
Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
do not have permission to do that, you may request the second reviewer to merge it for you.
## Code of Conduct
### Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
### Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
### Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
### Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
+193
View File
@@ -0,0 +1,193 @@
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
} = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.AddUser.Command,
description: cmdconfig.AddUser.Description,
type: ApplicationCommandType.ChatInput,
options: [
{
name: "user",
description: "The user to add",
type: ApplicationCommandOptionType.User,
required: true,
},
],
permissions: cmdconfig.AddUser.Permission,
async run(interaction) {
const userToAdd = interaction.options.getUser("user");
const ticketChannel = interaction.channel;
const ticketDataPath = "./Data/TicketData.json";
// Check if the channel is a ticket thread
if (!ticketChannel.isThread()) {
const onlyInTicket = new EmbedBuilder()
.setTitle(msgconfig.AddUser.NotInTicket_Title)
.setDescription(msgconfig.AddUser.NotInTicket_Description)
.setColor(supportbot.Embed.Colours.Error);
return interaction.reply({
embeds: [onlyInTicket],
ephemeral: true,
});
}
const ticketInviteEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Invite_Title)
.setDescription(msgconfig.AddUser.Invite_Description.replace("%username%", userToAdd.username))
.setColor(supportbot.Embed.Colours.General);
await interaction.reply({
embeds: [ticketInviteEmbed],
ephemeral: true,
});
try {
const dmEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.DM_Title)
.setDescription(msgconfig.AddUser.DM_Description.replace("%channelname%", ticketChannel.name))
.setColor(supportbot.Embed.Colours.General);
const acceptButton = new ButtonBuilder()
.setCustomId("accept_invite")
.setLabel(msgconfig.AddUser.Accept_Label)
.setEmoji("✅")
.setStyle(ButtonStyle.Primary);
const rejectButton = new ButtonBuilder()
.setCustomId("reject_invite")
.setLabel(msgconfig.AddUser.Reject_Label)
.setEmoji("❌")
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder().addComponents(acceptButton, rejectButton);
const dmMessage = await userToAdd.send({
embeds: [dmEmbed],
components: [row],
});
const filter = (i) => i.user.id === userToAdd.id;
const collector = dmMessage.createMessageComponentCollector({
filter,
time: 60000,
});
collector.on("collect", async (i) => {
if (i.customId === "accept_invite") {
try {
await ticketChannel.members.add(userToAdd.id);
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
if (ticketIndex !== -1) {
ticketData.tickets[ticketIndex].subUsers.push(userToAdd.id);
fs.writeFileSync(ticketDataPath, JSON.stringify(ticketData, null, 4));
}
const acceptedEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Accepted_Title)
.setDescription(msgconfig.AddUser.Accepted_Message)
.setColor(supportbot.Embed.Colours.Success);
await i.update({
embeds: [acceptedEmbed],
components: [],
});
const addedToTicketEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.AddedToTicket_Title)
.setDescription(msgconfig.AddUser.AddedToTicket_Description.replace(
"%channel_link%",
`[${ticketChannel.name}](https://discord.com/channels/${ticketChannel.guild.id}/${ticketChannel.id})`
))
.setColor(supportbot.Embed.Colours.General);
const ticketLinkButton = new ButtonBuilder()
.setLabel(msgconfig.AddUser.ViewTicket_Label)
.setURL(`https://discord.com/channels/${ticketChannel.guild.id}/${ticketChannel.id}`)
.setStyle(ButtonStyle.Link);
await userToAdd.send({
embeds: [addedToTicketEmbed],
components: [new ActionRowBuilder().addComponents(ticketLinkButton)],
});
} catch (err) {
console.error("Error adding user to the ticket:", err);
const errorEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Error_Title)
.setDescription(msgconfig.AddUser.Error_Adding)
.setColor(supportbot.Embed.Colours.Error);
await i.update({
embeds: [errorEmbed],
components: [],
});
}
} else {
const declinedEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Declined_Title)
.setDescription(msgconfig.AddUser.Declined_Message)
.setColor(supportbot.Embed.Colours.Error);
await i.update({
embeds: [declinedEmbed],
components: [],
});
}
});
collector.on("end", (collected) => {
if (collected.size === 0) {
userToAdd.send({
embeds: [
new EmbedBuilder()
.setTitle(msgconfig.AddUser.NoResponse_Title)
.setDescription(msgconfig.AddUser.NoResponse_Message)
.setColor(supportbot.Embed.Colours.Warning),
],
});
}
});
} catch (error) {
if (error.code === 50007) {
const errorEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.DM_Error_Title)
.setDescription(msgconfig.AddUser.DM_Error_Description.replace("%username%", userToAdd.username))
.setColor(supportbot.Embed.Colours.Error);
await ticketChannel.send({
embeds: [errorEmbed],
});
} else {
console.error("Error sending DM:", error);
const unexpectedErrorEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Unexpected_Error_Title)
.setDescription(msgconfig.AddUser.Unexpected_Error_Description.replace("%error%", error.message))
.setColor(supportbot.Embed.Colours.Error);
await ticketChannel.send({
embeds: [unexpectedErrorEmbed],
});
}
}
},
});
+336
View File
@@ -0,0 +1,336 @@
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
);
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.CloseTicket.Command,
description: cmdconfig.CloseTicket.Description,
type: Discord.ApplicationCommandType.ChatInput,
options: [
{
name: "reason",
description: "Ticket Close Reason",
type: Discord.ApplicationCommandOptionType.String,
},
],
permissions: cmdconfig.CloseTicket.Permission,
async run(interaction) {
const { getRole, getChannel } = interaction.client;
if (supportbot.Ticket.Close.StaffOnly) {
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new Discord.EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
!interaction.member.roles.cache.has(Admin.id)
)
return interaction.reply({ embeds: [NoPerms] });
}
if (interaction.channel.type !== Discord.ChannelType.PrivateThread) {
const NotTicketChannel = new Discord.EmbedBuilder()
.setTitle("Invalid Channel!")
.setDescription("This command can only be used in a ticket thread.")
.setColor(supportbot.Embed.Colours.Warn);
return interaction.reply({ embeds: [NotTicketChannel], ephemeral: true });
}
await interaction.deferReply();
let tickets = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
let TicketData = tickets.tickets.findIndex((t) => t.id === interaction.channel.id);
let ticket = tickets.tickets[TicketData];
if (TicketData === -1) {
const Exists = new Discord.EmbedBuilder()
.setTitle("No Ticket Found!")
.setDescription(msgconfig.Error.NoValidTicket)
.setColor(supportbot.Embed.Colours.Warn);
return interaction.followUp({ embeds: [Exists] });
}
let reason = interaction.options?.getString("reason") || "No Reason Provided.";
const CloseButton = new Discord.ButtonBuilder()
.setCustomId("confirmCloseTicket")
.setLabel(supportbot.Ticket.Close.Confirmation_Button)
.setEmoji(supportbot.Ticket.Close.Confirmation_Emoji)
.setStyle(supportbot.Ticket.Close.Confirmation_Style);
const row = new Discord.ActionRowBuilder().addComponents(CloseButton);
const CloseTicketRequest = new Discord.EmbedBuilder()
.setTitle(`**${supportbot.Ticket.Close.Title}**`)
.setDescription(
`${msgconfig.Ticket.ConfirmClose}`
)
.setColor(supportbot.Embed.Colours.General);
await interaction.followUp({
embeds: [CloseTicketRequest],
components: [row],
});
const filter = (btnInteraction) => btnInteraction.customId === "confirmCloseTicket" && btnInteraction.user.id === interaction.user.id;
interaction.channel.awaitMessageComponent({ filter, time: 20000 })
.then(async (btnInteraction) => {
await handleCloseTicket(interaction, reason, ticket, TicketData);
await btnInteraction.reply({ content: "Ticket successfully closed.", ephemeral: true });
})
.catch((err) => {
interaction.followUp(`${msgconfig.Ticket.CloseTimeout}`);
console.error(err);
});
},
});
async function handleCloseTicket(interaction, reason, ticket, TicketData) {
const { getChannel } = interaction.client;
let tickets = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
let tUser = interaction.client.users.cache.get(ticket.user);
let transcriptChannel = await getChannel(supportbot.Ticket.Log.TranscriptLog, interaction.guild);
let logChannel = await getChannel(supportbot.Ticket.Log.TicketLog, interaction.guild);
if (!transcriptChannel || !logChannel)
return interaction.followUp("Some Channels seem to be missing!");
try {
tickets.tickets[TicketData].open = false;
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(tickets, null, 4),
(err) => {
if (err) console.error(err);
}
);
const transcriptEmbed = new Discord.EmbedBuilder()
.setTitle(supportbot.Ticket.Log.TranscriptTitle)
.setColor(supportbot.Embed.Colours.General)
.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
})
.addFields(
{ name: "Ticket", value: `${interaction.channel.name} (${interaction.channel.id})` },
{ name: "User", value: `${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${tUser?.id || ticket.user})` },
{ name: "Closed By", value: interaction.user.tag },
{ name: "Reason", value: reason }
);
const logEmbed = new Discord.EmbedBuilder()
.setTitle(supportbot.Ticket.Log.TicketLog_Title)
.setColor(supportbot.Embed.Colours.General)
.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
})
.addFields(
{ name: "Ticket", value: `${interaction.channel.name} (${interaction.channel.id})` },
{ name: "User", value: `${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${tUser?.id || ticket.user})` },
{ name: "Closed By", value: interaction.user.tag },
{ name: "Reason", value: reason }
);
let msgs = await interaction.channel.messages.fetch({ limit: 100 });
let html = `
<html>
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
<style>
body {
background-color: #1a1a1a;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
margin: 0;
padding: 0;
height: 100%;
display: flex;
flex-direction: column;
}
.container {
backdrop-filter: blur(10px);
background-color: rgba(0, 128, 0, 0.3);
border-radius: 15px;
padding: 20px;
margin: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
flex-grow: 1;
display: flex;
flex-direction: column;
max-width: 1000px;
width: 100%;
margin: auto;
}
.message {
display: flex;
align-items: center;
margin-bottom: 10px;
padding: 10px;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 10px;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
}
.content {
flex: 1;
}
.username {
font-weight: bold;
}
.timestamp {
font-size: 0.8em;
color: #bbb;
}
.download-button {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin-top: 20px;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1 class="text-2xl font-bold mb-4">Ticket Transcript</h1>
<p><strong>Server Name:</strong> ${interaction.guild.name}</p>
<p><strong>Ticket:</strong> ${interaction.channel.name}</p>
<p><strong>Messages:</strong> ${msgs.size} Messages</p>
<div class="mt-4">
`;
msgs = msgs.sort((a, b) => a.createdTimestamp - b.createdTimestamp);
msgs.forEach((msg) => {
if (msg.content) {
html += `
<div class="message">
<img class="avatar" src="${msg.author.displayAvatarURL()}" alt="Avatar">
<div class="content">
<p class="username">${msg.author.tag}</p>
<p class="timestamp">${msg.createdAt.toLocaleString()}</p>
<p>${convertMarkdownToHTML(msg.content)}</p>
</div>
</div>
`;
}
});
const fileName = `${interaction.channel.name}.html`;
html += `
</div>
<a href="${fileName}" download class="download-button">Download Transcript</a>
</div>
</body>
</html>
`;
if (!supportbot.Ticket.Log.DisableTicketLogChannel) {
await logChannel.send({ embeds: [logEmbed] }).catch((err) => {
console.error(err);
});
}
let file = new Discord.AttachmentBuilder(
Buffer.from(html),
{ name: fileName }
);
await transcriptChannel
.send({ embeds: [transcriptEmbed], files: [file] })
.catch((err) => {
console.error(err);
});
if (supportbot.Ticket.DMTranscripts) {
await tUser
?.send({ embeds: [transcriptEmbed], files: [file] })
.catch((err) => {
console.error(err);
});
if (ticket.subUsers) {
ticket.subUsers.forEach(async (subUser) => {
await interaction.client.users.cache
.get(subUser)
?.send({ embeds: [transcriptEmbed], files: [file] });
});
}
}
await interaction.channel.delete().catch((error) => {
console.error(error);
if (error.code !== Discord.Constants.APIErrors.UNKNOWN_CHANNEL) {
console.error("Failed to delete the interaction:", error);
}
});
} catch (error) {
console.error(error);
}
}
function convertMarkdownToHTML(text) {
// Convert **bold** to <strong>bold</strong>
text = text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
// Convert *italic* to <em>italic</em>
text = text.replace(/\*(.*?)\*/g, '<em>$1</em>');
// Convert __underline__ to <u>underline</u>
text = text.replace(/__(.*?)__/g, '<u>$1</u>');
// Convert ~~strikethrough~~ to <s>strikethrough</s>
text = text.replace(/~~(.*?)~~/g, '<s>$1</s>');
// Convert inline code `code` to <code>code</code>
text = text.replace(/`(.*?)`/g, '<code>$1</code>');
// Convert blockquotes > quote to <blockquote>quote</blockquote>
text = text.replace(/^> (.*?$)/gm, '<blockquote>$1</blockquote>');
// Convert multiline code blocks ```code``` to <pre><code>code</code></pre>
text = text.replace(/```(.*?)```/gs, '<pre><code>$1</code></pre>');
// Convert line breaks to <br>
text = text.replace(/\n/g, '<br>');
return text;
}
+167
View File
@@ -0,0 +1,167 @@
// File path: ./commands/embed.js
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.Embed.Command,
description: cmdconfig.Embed.Description,
type: Discord.ApplicationCommandType.ChatInput,
options: [
{
name: "title",
description: "Embed Title",
type: Discord.ApplicationCommandOptionType.String,
required: true,
},
{
name: "message",
description: "Embed Message",
type: Discord.ApplicationCommandOptionType.String,
required: true,
},
{
name: "color",
description: "Embed HEX Color",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "fields",
description: "Embed Fields (title|content;title|content;...)",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "thumbnail",
description: "Embed Thumbnail URL",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "image",
description: "Embed Image URL",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "footer",
description: "Embed Footer Text",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "footericon",
description: "Embed Footer Icon URL",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "author",
description: "Embed Author Name",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "authoricon",
description: "Embed Author Icon URL",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "authorurl",
description: "Embed Author URL",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "timestamp",
description: "Include Timestamp",
type: Discord.ApplicationCommandOptionType.Boolean,
required: false,
},
{
name: "inline",
description: "Make Fields Inline",
type: Discord.ApplicationCommandOptionType.Boolean,
required: false,
}
],
permissions: cmdconfig.Embed.Permission,
async run(interaction) {
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin) {
return interaction.reply("Some roles seem to be missing!\nPlease check for errors when starting the bot.");
}
const NoPerms = new Discord.EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``)
.setColor(supportbot.Embed.Colours.Warn);
if (
interaction.member.roles.cache.has(SupportStaff.id) ||
interaction.member.roles.cache.has(Admin.id)
) {
const EmbedTitle = interaction.options.getString("title").replace(/\\n/g, '\n');
const EmbedSubject = interaction.options.getString("message").replace(/\\n/g, '\n');
const GeneralColour = interaction.options.getString("color") || supportbot.Embed.Colours.Default;
const EmbedThumbnail = interaction.options.getString("thumbnail");
const EmbedImage = interaction.options.getString("image");
const EmbedFields = interaction.options.getString("fields");
const EmbedFooter = interaction.options.getString("footer")?.replace(/\\n/g, '\n');
const EmbedFooterIcon = interaction.options.getString("footericon");
const EmbedAuthor = interaction.options.getString("author")?.replace(/\\n/g, '\n');
const EmbedAuthorIcon = interaction.options.getString("authoricon");
const EmbedAuthorURL = interaction.options.getString("authorurl");
const EmbedTimestamp = interaction.options.getBoolean("timestamp");
const InlineFields = interaction.options.getBoolean("inline");
const EmbedMsg = new Discord.EmbedBuilder()
.setTitle(EmbedTitle)
.setDescription(EmbedSubject)
.setColor(GeneralColour)
.setThumbnail(EmbedThumbnail)
.setImage(EmbedImage);
if (EmbedFields) {
const fieldsArray = EmbedFields.split(';');
fieldsArray.forEach(field => {
const [title, value] = field.split('|');
if (title && value) {
EmbedMsg.addFields({ name: title.replace(/\\n/g, '\n'), value: value.replace(/\\n/g, '\n'), inline: InlineFields || false });
}
});
}
if (EmbedFooter) {
EmbedMsg.setFooter({ text: EmbedFooter, iconURL: EmbedFooterIcon });
}
if (EmbedAuthor) {
EmbedMsg.setAuthor({ name: EmbedAuthor, iconURL: EmbedAuthorIcon, url: EmbedAuthorURL });
}
if (EmbedTimestamp) {
EmbedMsg.setTimestamp();
}
interaction.reply({
embeds: [EmbedMsg],
});
} else {
return interaction.reply({ embeds: [NoPerms] });
}
},
});
+119
View File
@@ -0,0 +1,119 @@
// File: Commands/ForceAddUser.js
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
} = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.ForceAddUser.Command,
description: cmdconfig.ForceAddUser.Description,
type: ApplicationCommandType.ChatInput,
options: [
{
name: "user",
description: "The user to add",
type: ApplicationCommandOptionType.User,
required: true,
},
],
permissions: cmdconfig.ForceAddUser.Permission,
async run(interaction) {
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
!interaction.member.roles.cache.has(Admin.id)
)
return interaction.reply({ embeds: [NoPerms] });
const userToAdd = interaction.options.getUser("user");
const ticketChannel = interaction.channel;
const ticketDataPath = "./Data/TicketData.json";
if (!ticketChannel.isThread()) {
const onlyInTicket = new EmbedBuilder()
.setTitle(msgconfig.ForceAddUser.NotInTicket_Title)
.setDescription(msgconfig.ForceAddUser.NotInTicket_Description)
.setColor(supportbot.Embed.Colours.Error);
return interaction.reply({
embeds: [onlyInTicket],
ephemeral: true,
});
}
try {
await ticketChannel.members.add(userToAdd.id);
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
if (ticketIndex !== -1) {
ticketData.tickets[ticketIndex].subUsers.push(userToAdd.id);
fs.writeFileSync(ticketDataPath, JSON.stringify(ticketData, null, 4));
}
const addedEmbed = new EmbedBuilder()
.setTitle(msgconfig.ForceAddUser.Added_Title)
.setDescription(msgconfig.ForceAddUser.Added_Description.replace(
"%username%",
userToAdd.username
))
.setColor(supportbot.Embed.Colours.Success);
await interaction.reply({
embeds: [addedEmbed],
ephemeral: true,
});
const addedToTicketEmbed = new EmbedBuilder()
.setTitle(msgconfig.ForceAddUser.AddedToTicket_Title)
.setDescription(msgconfig.ForceAddUser.AddedToTicket_Description.replace(
"%channel_link%",
`[${ticketChannel.name}](https://discord.com/channels/${ticketChannel.guild.id}/${ticketChannel.id})`
))
.setColor(supportbot.Embed.Colours.General);
await userToAdd.send({
embeds: [addedToTicketEmbed],
});
} catch (err) {
console.error("Error adding user to the ticket:", err);
const errorEmbed = new EmbedBuilder()
.setTitle(msgconfig.ForceAddUser.Error_Title)
.setDescription(msgconfig.ForceAddUser.Error_Adding)
.setColor(supportbot.Embed.Colours.Error);
await interaction.reply({
embeds: [errorEmbed],
ephemeral: true,
});
}
},
});
+62
View File
@@ -0,0 +1,62 @@
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.Help.Command,
description: cmdconfig.Help.Description,
type: Discord.ApplicationCommandType.ChatInput,
options: [],
permissions: cmdconfig.Help.Permission,
async run(interaction) {
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin) {
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
}
// Separate regular commands and addon commands
let botCommands = "";
let addonCommands = "";
interaction.client.commands.forEach((command) => {
if (command.permissions) {
if (command.addon) {
addonCommands += `\`${command.name}\` `;
} else {
botCommands += `\`${command.name}\` `;
}
}
});
// Create embed
const HelpEmbed1 = new Discord.EmbedBuilder()
.setTitle(supportbot.General.Name + " Commands")
.setThumbnail(interaction.user.displayAvatarURL())
.setColor(supportbot.Embed.Colours.General)
.addFields({
name: "🖥️ Commands\n",
value: botCommands || "No commands available.",
inline: false,
});
HelpEmbed1.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
});
interaction.reply({
ephemeral: true,
embeds: [HelpEmbed1],
});
},
});
+51
View File
@@ -0,0 +1,51 @@
// SupportBot | Emerald Services
// Info Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
);
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.Info.Command,
description: cmdconfig.Info.Description,
options: [],
permissions: cmdconfig.Info.Permission,
async run(interaction) {
let disableCommand = true;
const InfoButton = new Discord.ButtonBuilder()
.setLabel(msgconfig.Info.Button)
.setURL(msgconfig.Info.URL)
.setStyle("Link");
const inforow = new Discord.ActionRowBuilder().addComponents(InfoButton);
const InfoEmbed = new Discord.EmbedBuilder()
.setURL(msgconfig.Info.URL)
.setTitle(msgconfig.Info.Title)
.setDescription(msgconfig.Info.Description)
.setColor(msgconfig.Info.Colour)
interaction.reply({
embeds: [InfoEmbed],
components: [inforow],
});
},
});
+34
View File
@@ -0,0 +1,34 @@
// SupportBot | Emerald Services
// Ping Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.Ping.Command,
description: cmdconfig.Ping.Description,
options: [],
permissions: cmdconfig.Ping.Permission,
async run(interaction) {
let disableCommand = true;
const PingEmbed = new Discord.EmbedBuilder()
.setDescription(
`:ping_pong: **Ping:** \`${interaction.client.ws.ping} ms\``
)
.setColor(supportbot.Embed.Colours.General);
interaction.reply({
embeds: [PingEmbed],
});
},
});
+323
View File
@@ -0,0 +1,323 @@
const { EmbedBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ApplicationCommandType, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationCommandOptionType } = require("discord.js");
const fs = require("fs");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
const clockedInUsers = new Set();
async function getRole(roleName, guild) {
return guild.roles.cache.find(role => role.name === roleName);
}
function updateClockedInStatus(profileEmbed, clockedIn) {
profileEmbed.data.fields = profileEmbed.data.fields.map(field => {
if (field.name === 'Clocked In Status') {
field.value = clockedIn ? '✅ Clocked In' : '❌ Clocked Out';
}
return field;
});
return profileEmbed;
}
module.exports = new Command({
name: cmdconfig.Profile.Command,
description: cmdconfig.Profile.Description,
type: ApplicationCommandType.ChatInput,
permissions: cmdconfig.Profile.Permission,
options: [
{
name: 'user',
description: 'The user to view the profile of',
type: ApplicationCommandOptionType.User,
required: false
}
],
async run(interaction) {
await interaction.deferReply({ ephemeral: true }); // Acknowledge the interaction immediately
const userOption = interaction.options.getUser('user');
const viewingUser = userOption || interaction.user;
const viewingUserId = viewingUser.id;
const interactionUserId = interaction.user.id;
const user = interaction.guild.members.cache.get(viewingUserId);
const Staff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!Staff || !Admin) {
return interaction.editReply({
content: "Some roles seem to be missing!\nPlease check for errors when starting the bot.",
ephemeral: true,
});
}
const isStaff = user.roles.cache.has(Staff.id) || user.roles.cache.has(Admin.id);
const isOwnProfile = interactionUserId === viewingUserId;
const profilePath = `./Data/Profiles/${viewingUserId}.json`;
let profileData;
if (fs.existsSync(profilePath)) {
profileData = JSON.parse(fs.readFileSync(profilePath, "utf8"));
} else {
profileData = {
bio: "",
timezone: "",
clockedIn: false
};
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
}
const { bio, timezone, clockedIn } = profileData;
let profileEmbed = new EmbedBuilder()
.setTitle(`${viewingUser.username}'s Profile`)
.setColor(supportbot.Embed.Colours.General)
.setThumbnail(viewingUser.displayAvatarURL())
.addFields(
{ name: 'Bio', value: bio || 'No bio set.', inline: false },
{ name: 'Timezone', value: timezone || 'No timezone set.', inline: true }
);
if (isStaff) {
profileEmbed.addFields({ name: 'Clocked In Status', value: clockedIn ? '✅ Clocked In' : '❌ Clocked Out', inline: true });
}
const buttonRow = new ActionRowBuilder();
if (isOwnProfile) {
buttonRow.addComponents(
new ButtonBuilder()
.setCustomId('editProfile')
.setLabel('Edit Profile')
.setStyle(ButtonStyle.Secondary)
);
if (isStaff) {
buttonRow.addComponents(
new ButtonBuilder()
.setCustomId('clockInOut')
.setLabel(clockedIn ? 'Clock Out' : 'Clock In')
.setStyle(ButtonStyle.Secondary)
);
}
}
if (isStaff && supportbot.Ticket.ClaimTickets.Enabled) {
buttonRow.addComponents(
new ButtonBuilder()
.setCustomId('viewTicketStats')
.setLabel('View Ticket Stats')
.setStyle(ButtonStyle.Secondary)
);
}
await interaction.editReply({ embeds: [profileEmbed], components: buttonRow.components.length > 0 ? [buttonRow] : [] });
const filter = i => (
['editProfile', 'clockInOut', 'viewTicketStats', 'showOpenTickets', 'backToStats', 'backToProfile'].includes(i.customId)
&& i.user.id === interactionUserId
);
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 60000 });
collector.on('collect', async i => {
if (i.customId === 'editProfile') {
const modal = new ModalBuilder()
.setCustomId('editProfileModal')
.setTitle('Edit Profile')
.addComponents(
new ActionRowBuilder().addComponents(
new TextInputBuilder()
.setCustomId('bio')
.setLabel('Bio')
.setStyle(TextInputStyle.Paragraph)
.setPlaceholder('Enter your bio')
.setValue(String(bio))
.setRequired(false)
),
new ActionRowBuilder().addComponents(
new TextInputBuilder()
.setCustomId('timezone')
.setLabel('Timezone')
.setStyle(TextInputStyle.Short)
.setPlaceholder('Enter your timezone')
.setValue(String(timezone))
.setRequired(false)
)
);
await i.showModal(modal);
}
if (i.customId === 'clockInOut') {
profileData.clockedIn = !profileData.clockedIn;
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
profileEmbed = updateClockedInStatus(profileEmbed, profileData.clockedIn);
if (profileData.clockedIn) {
clockedInUsers.add(viewingUserId);
} else {
clockedInUsers.delete(viewingUserId);
}
const updatedButtonRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('editProfile')
.setLabel('Edit Profile')
.setStyle(ButtonStyle.Secondary)
);
if (isStaff) {
updatedButtonRow.addComponents(
new ButtonBuilder()
.setCustomId('clockInOut')
.setLabel(profileData.clockedIn ? 'Clock Out' : 'Clock In')
.setStyle(ButtonStyle.Secondary)
);
if (supportbot.Ticket.ClaimTickets.Enabled) {
updatedButtonRow.addComponents(
new ButtonBuilder()
.setCustomId('viewTicketStats')
.setLabel('View Ticket Stats')
.setStyle(ButtonStyle.Secondary)
);
}
}
await i.update({ embeds: [profileEmbed], components: [updatedButtonRow] });
let clockedinout = new EmbedBuilder()
.setTitle(profileData.clockedIn ? 'Clocked In!' : 'Clocked Out!')
.setDescription(profileData.clockedIn ? 'You have successfully clocked in.' : 'You have successfully clocked out.')
.setColor(supportbot.Embed.Colours.General)
await interaction.followUp({ embeds: [clockedinout], ephemeral: true });
}
if (i.customId === 'viewTicketStats') {
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const ticketsClaimed = TicketData.tickets.filter(t => t.claimedBy === viewingUserId);
const ticketsOpen = ticketsClaimed.filter(t => t.open);
const totalTickets = ticketsClaimed.length;
let totalResponseTime = 0;
let responseCount = 0;
ticketsClaimed.forEach(ticket => {
if (ticket.claimedAt && ticket.createdAt) {
const responseTime = new Date(ticket.claimedAt) - new Date(ticket.createdAt);
totalResponseTime += responseTime;
responseCount++;
}
});
const averageResponseTime = responseCount ? totalResponseTime / responseCount : 0;
const averageResponseTimeMinutes = Math.round(averageResponseTime / 60000);
const statsEmbed = new EmbedBuilder()
.setTitle(msgconfig.TicketStats.Title)
.setDescription(`> Ticket stats for <@${viewingUserId}>`)
.setColor(supportbot.Embed.Colours.General)
.addFields(
{ name: msgconfig.TicketStats.OpenTickets, value: `${ticketsOpen.length}`, inline: true },
{ name: msgconfig.TicketStats.TotalTickets, value: `${totalTickets}`, inline: true },
{ name: msgconfig.TicketStats.ResponseTime, value: `${averageResponseTimeMinutes} minutes`, inline: false }
);
const statsButtonRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('showOpenTickets')
.setLabel('Show Open Tickets')
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId('backToProfile')
.setLabel('Back to Profile')
.setStyle(ButtonStyle.Secondary)
);
await i.update({ embeds: [statsEmbed], components: [statsButtonRow] });
}
if (i.customId === 'showOpenTickets') {
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const ticketsOpen = TicketData.tickets.filter(t => t.claimedBy === viewingUserId && t.open);
const openTicketsEmbed = new EmbedBuilder()
.setTitle('Active Tickets')
.setDescription(ticketsOpen.map(t => `<#${t.id}>`).join('\n') || 'No active tickets.')
.setColor(supportbot.Embed.Colours.General);
const openTicketsButtonRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('backToStats')
.setLabel('Back to Stats')
.setStyle(ButtonStyle.Secondary)
);
await i.update({ embeds: [openTicketsEmbed], components: [openTicketsButtonRow] });
}
if (i.customId === 'backToStats') {
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const ticketsClaimed = TicketData.tickets.filter(t => t.claimedBy === viewingUserId);
const ticketsOpen = ticketsClaimed.filter(t => t.open);
const totalTickets = ticketsClaimed.length;
let totalResponseTime = 0;
let responseCount = 0;
ticketsClaimed.forEach(ticket => {
if (ticket.claimedAt && ticket.createdAt) {
const responseTime = new Date(ticket.claimedAt) - new Date(ticket.createdAt);
totalResponseTime += responseTime;
responseCount++;
}
});
const averageResponseTime = responseCount ? totalResponseTime / responseCount : 0;
const averageResponseTimeMinutes = Math.round(averageResponseTime / 60000);
const statsEmbed = new EmbedBuilder()
.setTitle(msgconfig.TicketStats.Title)
.setDescription(`> Ticket stats for <@${viewingUserId}>`)
.setColor(supportbot.Embed.Colours.General)
.addFields(
{ name: msgconfig.TicketStats.OpenTickets, value: `${ticketsOpen.length}`, inline: true },
{ name: msgconfig.TicketStats.TotalTickets, value: `${totalTickets}`, inline: true },
{ name: msgconfig.TicketStats.ResponseTime, value: `${averageResponseTimeMinutes} minutes`, inline: false }
);
const statsButtonRow = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('showOpenTickets')
.setLabel('Show Open Tickets')
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId('backToProfile')
.setLabel('Back to Profile')
.setStyle(ButtonStyle.Secondary)
);
await i.update({ embeds: [statsEmbed], components: [statsButtonRow] });
}
if (i.customId === 'backToProfile') {
await i.update({ embeds: [profileEmbed], components: buttonRow.components.length > 0 ? [buttonRow] : [] });
}
});
}
});
module.exports.clockedInUsers = clockedInUsers;
+125
View File
@@ -0,0 +1,125 @@
// File path: Commands/RemoveUser.js
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
} = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.RemoveUser.Command,
description: cmdconfig.RemoveUser.Description,
type: ApplicationCommandType.ChatInput,
options: [
{
name: "user",
description: "The user to remove",
type: ApplicationCommandOptionType.User,
required: true,
},
],
permissions: cmdconfig.RemoveUser.Permission,
async run(interaction) {
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
!interaction.member.roles.cache.has(Admin.id)
)
return interaction.reply({ embeds: [NoPerms] });
const userToRemove = interaction.options.getUser("user");
const ticketChannel = interaction.channel;
const ticketDataPath = "./Data/TicketData.json";
// Check if the channel is a ticket thread
if (!ticketChannel.isThread()) {
const onlyInTicket = new EmbedBuilder()
.setTitle(msgconfig.RemoveUser.NotInTicket_Title)
.setDescription(msgconfig.RemoveUser.NotInTicket_Description)
.setColor(supportbot.Embed.Colours.Error);
return interaction.reply({
embeds: [onlyInTicket],
ephemeral: true,
});
}
try {
await ticketChannel.members.remove(userToRemove.id);
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
if (ticketIndex !== -1) {
const subUsers = ticketData.tickets[ticketIndex].subUsers;
const userIndex = subUsers.indexOf(userToRemove.id);
if (userIndex !== -1) {
subUsers.splice(userIndex, 1);
fs.writeFileSync(ticketDataPath, JSON.stringify(ticketData, null, 4));
}
}
const removedEmbed = new EmbedBuilder()
.setTitle(msgconfig.RemoveUser.Removed_Title)
.setDescription(msgconfig.RemoveUser.Removed_Message)
.setColor(supportbot.Embed.Colours.Success);
await interaction.reply({
embeds: [removedEmbed],
ephemeral: true,
});
const removedFromTicketEmbed = new EmbedBuilder()
.setTitle(msgconfig.RemoveUser.RemovedFromTicket_Title)
.setDescription(msgconfig.RemoveUser.RemovedFromTicket_Description.replace(
"%channel_link%",
`[${ticketChannel.name}](https://discord.com/channels/${ticketChannel.guild.id}/${ticketChannel.id})`
))
.setColor(supportbot.Embed.Colours.General);
await userToRemove.send({
embeds: [removedFromTicketEmbed],
});
} catch (err) {
console.error("Error removing user from the ticket:", err);
const errorEmbed = new EmbedBuilder()
.setTitle(msgconfig.RemoveUser.Error_Title)
.setDescription(msgconfig.RemoveUser.Error_Removing)
.setColor(supportbot.Embed.Colours.Error);
await interaction.reply({
embeds: [errorEmbed],
ephemeral: true,
});
}
},
});
+115
View File
@@ -0,0 +1,115 @@
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
// Load configurations
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
// Ensure suggestions file exists and is correctly loaded
let suggestions;
try {
suggestions = require("../Data/SuggestionData.json");
} catch (error) {
suggestions = {};
}
module.exports = new Command({
name: cmdconfig.Suggestion.Command,
description: cmdconfig.Suggestion.Description,
type: Discord.ApplicationCommandType.ChatInput,
options: [
{
name: "suggestion",
description: "Create a Suggestion",
type: Discord.ApplicationCommandOptionType.String,
required: true,
},
],
permissions: cmdconfig.Suggestion.Permission,
async run(interaction) {
const { getChannel } = interaction.client;
const suggestChannel = await getChannel(
supportbot.Suggestions.Channel,
interaction.guild
);
const NoChannel = new Discord.EmbedBuilder()
.setTitle("Missing Channel!")
.setDescription(msgconfig.Error.InvalidChannel)
.setColor(supportbot.Embed.Colours.Error);
if (!suggestChannel) return interaction.reply({ embeds: [NoChannel] });
let suggestion = interaction.options.getString("suggestion");
const SuggestEmbed = new Discord.EmbedBuilder()
.addFields(
{ name: "Suggestion", value: suggestion, inline: true },
{ name: "From", value: `<@${interaction.user.id}>` },
{ name: `${supportbot.Suggestions.UpvoteEmoji} ${supportbot.Suggestions.UpvoteTitle}`, value: "0", inline: true },
{ name: `${supportbot.Suggestions.DownvoteEmoji} ${supportbot.Suggestions.DownvoteTitle}`, value: "0", inline: true }
)
.setThumbnail(interaction.user.displayAvatarURL())
.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
})
.setColor(supportbot.Embed.Colours.General);
const UpvoteButton = new Discord.ButtonBuilder()
.setCustomId("upvote")
.setEmoji(supportbot.Suggestions.UpvoteEmoji)
.setStyle(supportbot.Suggestions.Buttons.Upvote);
const DownvoteButton = new Discord.ButtonBuilder()
.setCustomId("downvote")
.setEmoji(supportbot.Suggestions.DownvoteEmoji)
.setStyle(supportbot.Suggestions.Buttons.Downvote);
const RemoveVoteButton = new Discord.ButtonBuilder()
.setCustomId("removevote")
.setLabel(supportbot.Suggestions.Buttons.RemoveVote_Title)
.setStyle(supportbot.Suggestions.Buttons.RemoveVote); // Red button
const row = new Discord.ActionRowBuilder().addComponents(UpvoteButton, DownvoteButton, RemoveVoteButton);
const suggestionMsg = await suggestChannel.send({ embeds: [SuggestEmbed], components: [row] });
suggestions[suggestionMsg.id] = {
suggestion: suggestion,
author: interaction.user.id,
upvotes: [],
downvotes: []
};
fs.writeFileSync("./Data/SuggestionData.json", JSON.stringify(suggestions, null, 2));
if (supportbot.Suggestions.Threads.Enabled) {
await suggestionMsg.startThread({
name: supportbot.Suggestions.Threads.Title,
autoArchiveDuration: 60,
type: Discord.ChannelType.PublicThread,
reason: supportbot.Suggestions.Threads.Reason,
});
}
const Submitted = new Discord.EmbedBuilder()
.setTitle(`${msgconfig.Suggestions.Sent_Title}`)
.setDescription(`${msgconfig.Suggestions.Sent}`)
.addFields(
{ name: "Sent to:", value: `<#${suggestChannel.id}>` },
)
.setColor(supportbot.Embed.Colours.Success);
await interaction.reply({
ephemeral: true,
embeds: [Submitted]
});
},
});
+461
View File
@@ -0,0 +1,461 @@
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
ChannelType,
ActionRowBuilder,
ButtonBuilder,
StringSelectMenuBuilder,
StringSelectMenuOptionBuilder,
ButtonStyle,
} = require("discord.js");
const yaml = require("js-yaml");
const panelconfig = yaml.load(fs.readFileSync("./Configs/ticket-panel.yml", "utf8"));
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
const TicketNumberID = require("../Structures/TicketID.js");
async function getClockedInUsers(guild) {
const clockedInUsers = new Set();
const profilesDir = './Data/Profiles';
const profileFiles = fs.readdirSync(profilesDir);
for (const file of profileFiles) {
const profileData = JSON.parse(fs.readFileSync(`${profilesDir}/${file}`, "utf8"));
if (profileData.clockedIn) {
const userId = file.replace('.json', '');
const member = await guild.members.fetch(userId);
if (member) clockedInUsers.add(member.id);
}
}
return clockedInUsers;
}
async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, attempts = 0) {
console.log(`Assigning ticket attempt ${attempts}`);
try {
const clockedInUsers = await getClockedInUsers(interaction.guild);
console.log(`Clocked in users: ${Array.from(clockedInUsers).join(', ')}`);
if (clockedInUsers.size === 0 || attempts >= 2) {
console.log("No clocked in users or max attempts reached");
const claimChannel = await interaction.guild.channels.cache.get(supportbot.Ticket.ClaimTickets.Channel);
if (claimChannel) {
const claimEmbed = new EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle || 'Default Claim Title')
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage || 'Default Claim Message')
.setColor(supportbot.Embed.Colours.General);
const claimButton = new ButtonBuilder()
.setCustomId(`claimticket-${ticketChannel.id}`)
.setLabel(supportbot.Ticket.ClaimTickets.ButtonTitle || 'Claim Ticket')
.setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(claimButton);
const claimMessage = await claimChannel.send({
content: `<@&${Staff.id}> <@&${Admin.id}>`,
embeds: [claimEmbed],
components: [row],
});
const filter = i => i.customId === `claimticket-${ticketChannel.id}` && i.member.roles.cache.has(Staff.id);
const collector = claimMessage.createMessageComponentCollector({ filter, time: 120000 });
collector.on('collect', async i => {
console.log(`Ticket claimed by user ${i.user.id}`);
await ticketChannel.send({ content: `<@${i.user.id}> has claimed the ticket.` });
});
collector.on('end', async collected => {
if (collected.size === 0) {
console.log("No one claimed the ticket, notifying admins");
await claimMessage.delete();
await claimChannel.send({
content: `No one claimed the ticket. Tagging roles: <@&${Staff.id}> <@&${Admin.id}>`,
embeds: [new EmbedBuilder().setDescription(`Ticket is still unclaimed: <#${ticketChannel.id}>`).setColor(supportbot.Embed.Colours.Warn)],
});
}
});
return null;
} else {
console.error("Claim channel not found");
return null;
}
}
const clockedInArray = Array.from(clockedInUsers);
const assignedUserId = clockedInArray[Math.floor(Math.random() * clockedInArray.length)];
const assignedUser = await interaction.guild.members.fetch(assignedUserId);
console.log(`Assigned user: ${assignedUserId}`);
const claimEmbed = new EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle || 'Default Claim Title')
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage.replace('%user%', interaction.user.id) || 'Default Claim Message')
.setColor(supportbot.Embed.Colours.General);
const claimButton = new ButtonBuilder()
.setCustomId(`claimticket-${ticketChannel.id}`)
.setLabel(supportbot.Ticket.ClaimTickets.ButtonTitle || 'Claim Ticket')
.setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(claimButton);
const claimChannel = await interaction.guild.channels.cache.get(supportbot.Ticket.ClaimTickets.Channel);
if (!claimChannel) {
console.error("Claim channel not found");
return null;
}
const claimMessage = await claimChannel.send({
content: `${assignedUser}`,
embeds: [claimEmbed],
components: [row],
});
const filter = i => i.customId === `claimticket-${ticketChannel.id}` && i.user.id === assignedUserId;
const collector = claimMessage.createMessageComponentCollector({ filter, time: 120000 });
collector.on('collect', async i => {
console.log(`Ticket claimed by user ${i.user.id}`);
await ticketChannel.send({ content: `<@${assignedUserId}>` });
});
collector.on('end', async collected => {
if (collected.size === 0) {
console.log("No one claimed the ticket, attempting reassignment");
await claimMessage.delete();
if (attempts >= 1) {
await claimChannel.send({
content: `No one claimed the ticket. Tagging roles: <@&${Staff.id}> <@&${Admin.id}>`,
embeds: [new EmbedBuilder().setDescription(`Ticket is still unclaimed: <#${ticketChannel.id}>`).setColor(supportbot.Embed.Colours.Warn)],
});
// Add a claim button for any staff member to click
const claimEmbed = new EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage)
.setColor(supportbot.Embed.Colours.General);
const claimButton = new ButtonBuilder()
.setCustomId(`claimticket-${ticketChannel.id}`)
.setLabel(supportbot.Ticket.ClaimTickets.ButtonTitle)
.setEmoji(supportbot.Ticket.ClaimTickets.ButtonEmoji)
.setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(claimButton);
const claimMessage = await claimChannel.send({
content: `<@&${Staff.id}> <@&${Admin.id}>`,
embeds: [claimEmbed],
components: [row],
});
const filter = i => i.customId === `claimticket-${ticketChannel.id}` && i.member.roles.cache.has(Staff.id);
const collector = claimMessage.createMessageComponentCollector({ filter, time: 120000 });
collector.on('collect', async i => {
console.log(`Ticket ${ticketChannel.id} claimed by user ${i.user.id}`);
await ticketChannel.member.add(i.user.id);
});
collector.on('end', async collected => {
if (collected.size === 0) {
console.log(`No one claimed the ticket (${ticketChannel.id}), notifying all staff`);
await claimMessage.delete();
await claimChannel.send({
content: `No one claimed the ticket. Tagging roles: <@&${Staff.id}> <@&${Admin.id}>`,
});
}
});
} else {
const ReassigningEmbed = new EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.ReassigningTitle)
.setDescription(msgconfig.Ticket.ClaimTickets.ReassigningMessage.replace('%user%', assignedUserId))
.setColor(supportbot.Embed.Colours.General);
await claimChannel.send({ embeds: [ReassigningEmbed], components: [] });
await assignTicketToUser(ticketChannel, Staff, Admin, interaction, attempts + 1);
}
}
});
return assignedUserId;
} catch (error) {
console.error("Error in assignTicketToUser function:", error);
if (error instanceof CombinedError) {
console.error("CombinedError details:", error.errors);
}
return null;
}
}
module.exports = new Command({
name: cmdconfig.OpenTicket.Command,
description: cmdconfig.OpenTicket.Description,
type: ApplicationCommandType.ChatInput,
options: [
{
name: "reason",
description: "Ticket Reason",
type: ApplicationCommandOptionType.String,
},
],
permissions: cmdconfig.OpenTicket.Permission,
async run(interaction) {
try {
let TicketReason = null;
if (supportbot.Ticket.TicketReason) {
TicketReason = interaction.reason || null; // Retrieve the reason from the interaction object
}
let TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const { getRole, getChannel } = interaction.client;
let User = interaction.guild.members.cache.get(interaction.user.id);
if (
supportbot.Ticket.TicketsPerUser &&
TicketData.tickets.filter((t) => t.user === interaction.user.id && t.open).length >= supportbot.Ticket.TicketsPerUser
) {
return interaction.reply({
embeds: [
{
title: "Too Many Tickets!",
description: `You can't have more than ${supportbot.Ticket.TicketsPerUser} open tickets!`,
color: supportbot.Embed.Colours.Warn,
},
],
ephemeral: true,
});
}
if (User.roles.cache.has(supportbot.Roles.ModRoles.Blacklisted)) {
return interaction.reply({
content: msgconfig.Ticket.Blacklisted,
ephemeral: true,
});
}
if (User.roles.cache.has(supportbot.Roles.ModRoles.Muted)) {
return interaction.reply({
content: msgconfig.Ticket.Muted,
ephemeral: true,
});
}
let ticketNumberID = await TicketNumberID.pad();
const TicketSubject = TicketReason || msgconfig.Ticket.InvalidSubject;
const TicketExists = new EmbedBuilder()
.setTitle("Ticket Exists!")
.setDescription(msgconfig.Ticket.TicketExists);
if (
await interaction.guild.channels.cache.find(
(ticketChannel) => ticketChannel.name === `${supportbot.Ticket.Channel}${ticketNumberID}`
)
) {
return await interaction.reply({
embeds: [TicketExists],
ephemeral: true,
});
}
const Staff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!Staff || !Admin)
return interaction.reply({
content: "Some roles seem to be missing!\nPlease check for errors when starting the bot.",
ephemeral: true,
});
const TicketCategory = interaction.guild.channels.cache.find(
(c) => c.name === supportbot.Ticket.TicketCategory || c.id === supportbot.Ticket.TicketCategory
);
const channel = await getChannel(supportbot.Ticket.TicketCategory, interaction.guild);
const ticketChannel = await channel.threads.create({
name: `${supportbot.Ticket.Channel}${ticketNumberID}`,
type: ChannelType.PrivateThread,
parent: TicketCategory,
autoArchiveDuration: 60,
reason: 'support ticket',
});
// Assign ticket to a user if claiming tickets is enabled
if (supportbot.Ticket.ClaimTickets.Enabled) {
const assignedUserId = await assignTicketToUser(ticketChannel, Staff, Admin, interaction);
if (!assignedUserId) {
const claimChannel = await interaction.guild.channels.cache.get(supportbot.Ticket.ClaimTickets.Channel);
await claimChannel.send(`<@&${Staff.id}> <@&${Admin.id}>`);
}
}
// Add user to the ticket channel
await ticketChannel.members.add(interaction.user.id);
// Save ticket data
TicketData.tickets.push({
id: ticketChannel.id,
name: ticketChannel.name,
user: interaction.user.id,
number: ticketNumberID,
reason: TicketSubject,
open: true,
subUsers: [],
createdAt: new Date().toISOString(),
claimedAt: null,
});
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(TicketData, null, 4),
(err) => {
if (err) console.error(err);
}
);
// Notify the user that the ticket was created
const CreatedTicket = new EmbedBuilder()
.setDescription(
msgconfig.Ticket.TicketCreatedAlert.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username)
.replace(/%ticketreason%/g, TicketSubject)
)
.setColor(supportbot.Embed.Colours.General);
await interaction.reply({ embeds: [CreatedTicket], ephemeral: true });
// Create the ticket message
const TicketMessage = new EmbedBuilder()
.setAuthor({
name: msgconfig.Ticket.TicketAuthorTitle.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username),
iconURL: interaction.user.displayAvatarURL(),
})
.setTitle(
msgconfig.Ticket.TicketTitle.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username)
)
.setDescription(
msgconfig.Ticket.TicketMessage.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username)
.replace(/%ticketreason%/g, TicketSubject)
)
.setColor(supportbot.Embed.Colours.General);
// Add reason field if ticket reason is enabled
if (supportbot.Ticket.TicketReason && TicketReason) {
TicketMessage.addFields(
{ name: "Reason", value: TicketReason, inline: false }
);
}
// Create the control panel
const SelectMenus = new StringSelectMenuBuilder()
.setCustomId("ticketcontrolpanel")
.setPlaceholder("Ticket Control Panel")
.addOptions(
new StringSelectMenuOptionBuilder()
.setLabel("Close")
.setDescription("Close the ticket.")
.setEmoji(supportbot.SelectMenus.Tickets.CloseEmoji)
.setValue("ticketclose"),
new StringSelectMenuOptionBuilder()
.setLabel("Archive")
.setDescription("Acrhive the ticket.")
.setEmoji(supportbot.SelectMenus.Tickets.ArchiveEmoji)
.setValue("archiveticket"),
new StringSelectMenuOptionBuilder()
.setLabel("Lock Ticket")
.setDescription("Lock the ticket.")
.setEmoji(supportbot.SelectMenus.Tickets.LockEmoji)
.setValue("lockticket"),
new StringSelectMenuOptionBuilder()
.setLabel("Enable Invites")
.setDescription("Enable invites.")
.setEmoji(supportbot.SelectMenus.Tickets.EnableInvitesEmoji)
.setValue("enableinvites"),
new StringSelectMenuOptionBuilder()
.setLabel("Disable Invites")
.setDescription("Disable invites.")
.setEmoji(supportbot.SelectMenus.Tickets.DisableInvitesEmoji)
.setValue("disableinvites"),
);
const row2 = new ActionRowBuilder().addComponents(SelectMenus);
// Send the ticket message and control panel
await ticketChannel.send({
embeds: [TicketMessage],
components: [row2],
});
// Handle department selection if not specified
if (!department) {
try {
const buttons = supportbot.Departments.map((x, index) =>
new ButtonBuilder()
.setCustomId("Department" + index)
.setLabel(x.title)
.setStyle(x.color)
.setEmoji(x.emoji)
);
const row = new ActionRowBuilder().addComponents(buttons);
const message = await ticketChannel.send({
content: "Please select a department:",
components: [row],
});
const filter = (i) => i.user.id === interaction.user.id;
await message.awaitMessageComponent({
filter,
max: 1,
componentType: "BUTTON",
time: supportbot.Ticket.Timeout * 60000,
});
} catch (e) {
if (e.code === "COLLECTOR_ERROR") {
try {
const ticket = TicketData.tickets.findIndex((t) => t.id === ticketChannel.id);
TicketData.tickets[ticket].open = false;
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(TicketData, null, 4),
(err) => {
if (err) console.error(err);
}
);
await interaction.user.send(
"Your ticket has timed out. Please open a new one and select a department."
);
} catch (error) {
console.error("An error occurred while handling collector:", error);
}
await ticketChannel.delete();
}
}
}
} catch (error) {
console.error("Error in run method:", error);
}
},
});
+115
View File
@@ -0,0 +1,115 @@
// ticketpanel.js
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandType,
ActionRowBuilder,
ButtonBuilder,
} = require("discord.js");
const yaml = require("js-yaml");
const panelconfig = yaml.load(fs.readFileSync("./Configs/ticket-panel.yml", "utf8"));
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.TicketPanel.Command,
description: cmdconfig.TicketPanel.Description,
type: ApplicationCommandType.ChatInput,
options: [],
permissions: cmdconfig.TicketPanel.Permission,
async run(interaction) {
if (!panelconfig.Panel) {
console.log(
"\u001b[31m",
`[TICKET PANEL]`,
"\u001b[33m",
"Ticket Panel is not setup, You can set this in", `\u001b[31m`, '/Configs/ticket-panel.yml', `\n `,
);
return interaction.reply({
content: "Ticket Panel is not set up. Please configure it in `/Configs/ticket-panel.yml`.",
ephemeral: true,
});
}
const channelName = panelconfig.Channel;
const channel = interaction.guild.channels.cache.find(ch => ch.name === channelName);
if (!channel) {
console.log(`[TICKET PANEL] ${channelName} channel not found. Please check your config file.`);
return interaction.reply({
content: `${channelName} channel not found. Please check your config file.`,
ephemeral: true,
});
}
const panelid = JSON.parse(fs.readFileSync("./Data/ticket-panel-id.json", "utf8"));
try {
await channel.messages.fetch(panelid.TicketPanelID);
return interaction.reply({
content: "Ticket panel message already exists.",
ephemeral: true,
});
} catch (error) {
let embed = new EmbedBuilder()
.setTitle(panelconfig.PanelTitle)
.setColor(panelconfig.PanelColour)
.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
});
if (panelconfig.TicketPanel_Description) {
embed.setDescription(panelconfig.PanelMessage);
}
if (panelconfig.TicketPanel_Thumbnail) {
embed.setThumbnail(panelconfig.PanelThumbnail);
}
if (panelconfig.TicketPanel_Image) {
embed.setImage(panelconfig.PanelImage);
}
const createTicketButton = new ButtonBuilder()
.setCustomId("createticket")
.setLabel(panelconfig.Button.Text)
.setEmoji(panelconfig.Button.Emoji)
.setStyle(panelconfig.Button.Color);
let row = new ActionRowBuilder().addComponents(createTicketButton);
try {
const message = await channel.send({
embeds: [embed],
components: [row],
});
let data = {
id: panelid.id,
TicketPanelID: message.id,
};
fs.writeFileSync(
"./Data/ticket-panel-id.json",
JSON.stringify(data),
"utf8"
);
return interaction.reply({
content: "Ticket panel message has been sent!",
ephemeral: true,
});
} catch (e) {
console.log("Error sending message:", e);
return interaction.reply({
content: "An error occurred while sending the ticket panel message.",
ephemeral: true,
});
}
}
},
});
+117
View File
@@ -0,0 +1,117 @@
// SupportBot | Emerald Services
// Translate Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
)
const Command = require("../Structures/Command.js");
const translate = require("@vitalets/google-translate-api");
module.exports = new Command({
name: cmdconfig.Translate.Command,
description: cmdconfig.Translate.Description,
type: Discord.ApplicationCommandType.ChatInput,
options: [
{
type: Discord.ApplicationCommandOptionType.String,
name: "language",
description: "A 2 letter language code",
required: true,
},
{
type: Discord.ApplicationCommandOptionType.String,
name: "text",
description: "The text to translate",
required: true,
}, // The input text for the translation
],
permissions: cmdconfig.Translate.Permission, // The permission the user/role at least requires
async run(interaction) {
let disableCommand = true;
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new Discord.EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
!interaction.member.roles.cache.has(Admin.id)
)
return interaction.reply({ embeds: [NoPerms] });
const { getChannel } = interaction.client;
let lang = interaction.options.getString("language"); // Grab choice of language code by user
let url = "https://www.science.co.il/language/Codes.php"; // URL to all available language codes
let text = await interaction.options.getString("text"); // Grab the text to translate by the user
let translatelog = await getChannel(
supportbot.Translate.Log,
interaction.guild
); // Grab the set logging channel for translations
// Return message if user has provided an invalid language code
const result = await translate(text, { to: lang }).catch(async (err) => {
if (err && err.code == 400) {
await interaction.reply({
embeds: [
new Discord.EmbedBuilder()
.setColor(supportbot.Embed.Colours.Warn)
.setTitle("Valid Language Codes")
.setURL(url)
.setDescription(
"Click the title to see which 2 letter language codes are valid."
),
],
ephemeral: true,
});
}
});
if (!result) return;
// Embed containing language code, original text and translated text
let transembed = new Discord.EmbedBuilder()
.setAuthor({ name: interaction.user.tag, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
.setColor(supportbot.Embed.Colours.Success)
.setDescription(`**Translation to ${lang}**`)
.addFields(
{ name: "Original text", value: text },
{ name: "Translated text", value: result.text },
)
.setFooter({ text: `Author: ${interaction.user.id}` })
.setTimestamp();
// Send embed [transembed] with translated message to channel
await interaction.reply({ embeds: [transembed] });
// Send embed [transembed] to logging channel
await translatelog.send({ embeds: [transembed] });
},
})
+115
View File
@@ -0,0 +1,115 @@
# ___ _ ___ _
# / __> _ _ ___ ___ ___ _ _ _| |_ | . > ___ _| |_
# \__ \| | || . \| . \/ . \| '_> | | | . \/ . \ | |
# <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_|
# |_| |_|
#
# SupportBot created by Emerald Services
# Installed with MIT License
#
# Discord Support: https://dsc.gg/emerald-dev
# Official Documentation: https://emeraldsrv.dev/wiki
# Third-Party Documentation: https://emeraldsrv.dev/third-party
#
# Command Configuration
Help:
Command: "help"
Description: "Get a list of all the commands."
Permission: ["SendMessages"]
Enabled: true
Info:
Command: "info"
Description: "Get information about the **ServerName**."
Permission: ["SendMessages"]
Enabled: true
TicketPanel:
Command: "ticketpanel"
Description: "Create the ticket creation panel"
Permission: ["Administrator"]
Enabled: true
Profile:
Command: "profile"
Description: "Shows the profile for a discord member."
Permission: ["SendMessages"]
# Command is automatically disabled when the TicketClaims is disabled.
OpenTicket:
Command: "ticket"
Description: "Create a support ticket."
Permission: ["SendMessages"]
Enabled: true
AddUser:
Command: "add"
Description: "Add a user to a support ticket."
Permission: ["SendMessages"]
Enabled: true
ForceAddUser:
Command: "forceadd"
Description: "Add a user to a support ticket by bypassing the invite system."
Permission: ["SendMessages"]
Enabled: true
RemoveUser:
Command: "remove"
Description: "Remove a user from a support ticket."
Permission: ["SendMessages"]
Enabled: true
CloseTicket:
Command: "close"
Description: "Close a support ticket"
Permission: ["SendMessages"]
Enabled: true
Suggestion:
Command: "suggest"
Description: "Create a suggestion."
Permission: ["SendMessages"]
Enabled: true
Embed:
Command: "embed"
Description: "Build a discord embed."
Permission: ["SendMessages"]
Enabled: true
Translate:
Command: "translate"
Description: "Translate something to english"
Permission: ["SendMessages"]
Enabled: false
UserInfo:
Command: "userinfo"
Description: "Get info about a user."
Permission: ["SendMessages"]
Enabled: true
Ping:
Command: "ping"
Description: "Pong."
Permission: ["SendMessages"]
Enabled: true
# ---------------------------------------
# Command Description Configuration
# ---------------------------------------
BlacklistDesc: "Blacklist a user from creating Tickets."
TicketAddDesc: "Add a user to a support ticket."
TicketRemoveDesc: "Remove a user from a support ticket."
TranslateCommandDesc: "Translates the language provided, along with the abbreviation (2 char) long language code"
OpenTicketDesc: "Open a new support ticket."
CloseTicketDesc: "Close your support ticket."
InfoCommandDesc: "Get information about the brand."
PingCommandDesc: "Pong!"
HelpCommandDesc: "Get a list of all the commands."
EmbedCommandDesc: "Send a message as an embed."
SuggestCommandDesc: "Suggest a feature for the server."
UserInfoCommandDesc: "Get info about a user."
+178
View File
@@ -0,0 +1,178 @@
# ___ _ ___ _
# / __> _ _ ___ ___ ___ _ _ _| |_ | . > ___ _| |_
# \__ \| | || . \| . \/ . \| '_> | | | . \/ . \ | |
# <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_|
# |_| |_|
#
# SupportBot created by Emerald Services
# Installed with MIT License
#
# Discord Support: https://dsc.gg/emerald-dev
# Official Documentation: https://emeraldsrv.com/wiki
# Third-Party Documentation: https://emeraldsrv.com/third-party
#
# Messages Configuration
Info:
Title: "About Us"
Description: "SupportBot is an open-sourced support system for discord. It's completely free to use with high amounts of customization to match your own brand."
Button: "Visit Site"
URL: "https://emeraldsrv.com"
Colour: "#f74343"
Welcome:
Embed:
Colour: "#f74343"
Title: "Welcome to ServerName"
Message: ":smile: %joined_user% has just landed!"
Thumbnail: "BOT"
ImageEnabled: false
ImageURL: "https://animagelink.png/"
Leave:
Embed:
Colour: "#f74343"
Title: "Goodbye!"
Message: ":slight_frown: %joined_user% has recently dropped out!"
Thumbnail: "BOT"
ImageEnabled: false
ImageURL: "https://animagelink.png/"
Suggestions:
Sent_Title: "Suggestion Sent!"
Sent: ":white_check_mark: **You have successfully sent a suggestion.**"
NoSelfVote: ":x: **You cannot vote on your own suggestion.**"
RemoveVoteButton: "Remove Vote"
Ticket:
# Available Placeholders:
# %ticketusername% - User who created the ticket.
# <@%ticketauthor%> - Tags the user who created the ticket.
# <#%ticketid%> - Mentions the ticket channel.
TicketAuthorTitle: "%ticketusername%'s Ticket"
TicketTitle: "Support Ticket"
TicketMessage: "Hello <@%ticketauthor%>, Thank you for creating a support ticket\nPlease wait patiently whilst a member of our team reaches out to you."
TicketThumbnail: "https://images.emojiterra.com/google/android-pie/512px/1f39f.png"
TicketCreatedAlert: ":ticket: Ticked Created: <#%ticketid%>"
TicketExists: "❌ Ticket already exists"
TicketClaim: ":white_check_mark: Ticket claimed by" #The user who claimed the ticket will be added to the end of this message
TicketUnclaim: ":white_check_mark: Ticket unclaimed by" #The user who claimed the ticket will be added to the end of this message
TicketArchived: ":white_check_mark: Ticket archived."
TicketUnarchived: ":white_check_mark: Ticket unarchived."
TicketLocked: ":lock: Ticket is locked."
DisableInvites: "🔒 Invites have been disabled for this ticket."
EnableInvites: "🔓 Invites have been enabled for this ticket."
# Available Placeholders:
# <@%user%> - Tags the user who was added to the ticket.
Blacklisted: ":x: You are not allowed to open a ticket"
Muted: ":x: You are `Muted` and therefore not allowed to open any tickets"
InvalidSubject: "No Reason Provided!"
TranscriptSavedMessage: "📝 **Transcript Saved!**"
TicketLockMessage: "❌ **Ticket Locked!**"
TicketDeleteMessage: "⚠ **Ticket Deleting!**"
ClosingTicket: ":warning: You have requested to close your support ticket."
ConfirmClose: "Please confirm closing the ticket by clicking the button below."
CloseTimeout: "Ticket close confirmation timed out."
ClaimTickets:
ClaimTitle: "Incoming Support Request!"
ClaimMessage: "A new ticket has been created by <@!%user%>. Click the button below to claim this ticket."
ClaimMessage_Edit: "<#%channel%> was claimed by <@!%user%>."
ClaimedTitle: "Ticket Claimed!"
Claimed: "You have successfully claimed this ticket. <#%channel%>"
NoPermsToClaimTitle: "Error, no permissions!"
NoPermsToClaim: ":x: **Err!** You do not permissions to claim this ticket."
ReassigningTitle: "Reassigning!..."
ReassigningMessage: "<@%user%> did not claim the ticket. **Reassigning...**"
TicketStats:
OpenTickets: "✅ Open Tickets"
TotalTickets: "🎫 Total Tickets"
ResponseTime: "⏱️ Average Response Time"
Title: "Your Ticket Stats"
AddUser:
NotInTicket_Title: "Ticket Invitation"
NotInTicket_Description: "This command can only be used within a ticket thread."
Invite_Title: "User Invited"
Invite_Description: "%username% has been invited to join the ticket."
DM_Title: "Ticket Invitation"
DM_Description: "You have been invited to join the ticket %channelname%. Do you accept?"
Accept_Label: "Accept"
Reject_Label: "Reject"
ViewTicket_Label: "Go to Ticket"
Accepted_Title: "Invitation Accepted"
Accepted_Message: "You have been added to the ticket."
AddedToTicket_Title: "Added to Ticket"
AddedToTicket_Description: "You have been added to the ticket %channel_link%."
Declined_Title: "Invitation Declined"
Declined_Message: "You have declined the invitation."
NoResponse_Title: "No Response"
NoResponse_Message: "You did not respond in time. Please contact staff if you wish to join the ticket."
Error_Title: "Error"
Error_Adding: "There was an error adding you to the ticket. Please try again."
DM_Error_Title: "Error"
DM_Error_Description: "Unable to send a DM to %username%. Please ensure your DMs are enabled."
Unexpected_Error_Title: "Error"
Unexpected_Error_Description: "An unexpected error occurred: %error%"
RemoveUser:
NotInTicket_Title: "Error"
NotInTicket_Description: "This command can only be used in ticket threads."
Removed_Title: "User Removed"
Removed_Message: "The user has been successfully removed from the ticket."
RemovedFromTicket_Title: "Removed from Ticket"
RemovedFromTicket_Description: "You have been removed from the ticket channel %channel_link%."
Error_Title: "Error"
Error_Removing: "There was an error removing the user from the ticket."
ForceAddUser:
NotInTicket_Title: "Not a Ticket"
NotInTicket_Description: "This command can only be used within a ticket thread."
Added_Title: "User Added"
Added_Description: "Successfully added %username% to the ticket."
AddedToTicket_Title: "You have been added to a Ticket"
AddedToTicket_Description: "You have been added to the ticket channel [%channel_link%]."
Error_Title: "Error"
Error_Adding: "There was an error adding the user to the ticket."
Error:
IncorrectPerms: ":x: **Err!** You do not have the correct permissions to use this."
InvalidChannel: ":x: **Err!** Channel not found. Please create it!"
UserNotFound: ":x: **Err!** This user doesn't exist, Are they in this server?"
NoValidTicket: ":warning: You cannot execute this command here."
TicketExists: ":warning: This ticket cannot be opened, It already exists!"
+39
View File
@@ -0,0 +1,39 @@
# -------------------------
# SupportBot AI
#
# In order to use the SupportBot AI, You need to setup an OpenAI Account.
# this can be done at https://platform.openai.com/
# -------------------------
Enabled: true
General:
Name: "SupportBot AI"
# What would you like to call your AI
Model: "gpt-4o"
# You can see a list of OpenAI Models here: https://platform.openai.com/docs/models
Tokens: 400
# Max tokens you can set is 400
# For more information about tokens, go to https://openai.com/api/pricing/
OpenAI_Key: "OPEN_AI_KEY_HERE"
# To create an OpenAI API key, go to https://platform.openai.com/api-keys
PastebinAPI_Key: "PASTEBIN_API_KEY_HERE"
# You can get your Pastebin API Key from https://pastebin.com
PastebinAPI_URL: "https://pastebin.com/api/api_post.php"
Channels:
AIChannel: "1250190338954498048"
# This is the channel where AI will respond in without needing to mention the bot.
Embed:
Color: 0x0cc559 # 0x<hexcode>
Footer: "SupportBot | Developed by Emerald Development"
Messages:
MessageTooLong: "The response was too long, so I've posted it here: {pastebin}"
ErrorResponse: "I didn't receive a proper response from OpenAI. Please try again later."
OpenAIError: "I'm having some trouble talking to SupportBot AI's Model, OpenAI. Please try again later."
AIDisabled: "I am disabled, You have enable me in `supportbot-ai.yml`"
+239
View File
@@ -0,0 +1,239 @@
# ___ _ ___ _
# / __> _ _ ___ ___ ___ _ _ _| |_ | . > ___ _| |_
# \__ \| | || . \| . \/ . \| '_> | | | . \/ . \ | |
# <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_|
# |_| |_|
#
# SupportBot created by Emerald Development
# Installed with MIT License
#
# Discord Support: https://dsc.gg/emerald-dev
# Official Documentation: https://github.com/Emerald-Services/SupportBot/wiki
# Third-Party Documentation: COMING SOON
SupportBot_Version: "v8.0.1"
# Do not change the version number
# -------------------------
# General
# -------------------------
General:
Name: "SupportBot"
Token: "BOT_TOKEN_HERE"
# To get your Discord Bot Token, Go to https://discord.com/developers/applications
Addons:
Enabled: true
# -------------------------
# Activity
# -------------------------
Activity:
Status: "SupportBot v8"
Type: "Competing"
# The Type can either be Playing, Watching, Listening or Competing
StreamingURL: "https://www.twitch.tv/YOUR_TWITCH_NAME"
# Set The Type to "Streaming" for a streaming status!
# -------------------------
# Embeds
# -------------------------
Embed:
Colours:
General: 0x0cc559 # 0x<hexcode>
Success: 0x04b545 # 0x<hexcode>
Error: 0xd13030 # 0x<hexcode>
Warn: 0xfca117 # 0x<hexcode>
Footer: "SupportBot | Developed by Emerald Development"
# -------------------------
# Roles
# -------------------------
Roles:
AutoRole:
Enabled: true
Role: "Member"
StaffMember:
Staff: "Staff"
Admin: "Admin"
ModRoles:
Muted: "Muted"
Blacklisted: "Blacklisted"
# ----------------------------
# System Messages
# ----------------------------
Welcome:
Enabled: true
Channel: "🚨┃join-leave-logs"
Leave:
Enabled: true
Channel: "🚨┃join-leave-logs"
# ----------------------------
# Suggestions
# ----------------------------
Suggestions:
Channel: "📗┃suggestions"
UpvoteEmoji: "✅"
DownvoteEmoji: "❌"
UpvoteTitle: "Yes"
DownvoteTitle: "No"
OwnSuggestion: true
# If false this will not allow the user to vote for a suggestion they created
# If true this will allow the user to vote for a suggestion they created
ShowUsers: true
Threads:
Enabled: true
Title: "Suggestion-releated Thread"
Reason: "A thread releted to this suggestion"
Buttons:
Upvote: "2"
Downvote: "2"
RemoveVote: "4"
RemoveVote_Title: "Remove Vote"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Green
# 4 - Red
# -------------------------
# Tickets
# -------------------------
Ticket:
TicketCategory: "📗┃tickets" #Where tickets normally go with the /ticket command
# This is the channel name for the ticket threads to be created, NOT A DISCORD CATEGORY!
Channel: "ticket-" # The prefix for ticket channel names
TicketsPerUser: 100
DMTranscripts: true
TicketReason: true
# If ticket reason is set to false, It will not prompt to create a reason
TicketSubject: "description"
# "description" will display the ticket reason within the channel description
# "embed" will display the ticket reason within the ticket embed
Timeout: 5
# Set to true to allow all staff to access the ticket
Log:
TicketLog: "🚨┃ticket-data"
TicketLog_Title: "Ticket Closed"
DisableTicketLogChannel: false
TranscriptLog: "🚨┃ticket-data"
TranscriptTitle: "Ticket Transcript"
Close:
StaffOnly: true
# Set to false is anyone is able to close a ticket.
Confirmation_Button: "Confirm Close"
Confirmation_Emoji: "🗑️"
Confirmation_Style: "2"
Title: "Are you sure you want to close this ticket?"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Green
# 4 - Red
Invites:
StaffOnly: true
LockedTickets:
Channel: "1267856939275124809"
ClaimTickets:
Enabled: true
Channel: "1249723473757077624"
# Channel name or Channel ID
ClaimAcceptTime: 120000
# How long the assigned user has to accept the ticket before it gets re-assigned to someone else.
ButtonTitle: "Claim Ticket"
ButtonEmoji: "🎫"
Button: "1"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Green
# 4 - Red
# -------------------------
# Departments - NOT IN THIS UPDATE
# -------------------------
Departments:
- title: "Create Ticket"
role: "Staff"
color: "2"
emoji: "🎫"
category: "TICKETS"
# -------------------------
# Buttons
# -------------------------
Buttons:
Tickets:
ClaimEmoji: "🧑‍💻"
ClaimStyle: "1"
Unarchive: "Unarchive Ticket"
Unarchive_Emoji: "♻️"
Unarchive_Style: "2"
Unlock: "Unlock Ticket"
Unlock_Emoji: "🔓"
Unlock_Style: "2"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Green
# 4 - Red
# -------------------------
# Select Menus
# -------------------------
SelectMenus:
Tickets:
PanelEmoji: "⚙️"
CloseEmoji: "🗑️"
ArchiveEmoji: "♻️"
LockEmoji: "🔐"
EnableInvitesEmoji: "📤"
DisableInvitesEmoji: "📥"
# -------------------------
# Misc
# -------------------------
Translate:
Log: "🚨┃logs"
+46
View File
@@ -0,0 +1,46 @@
# ___ _ ___ _
# / __> _ _ ___ ___ ___ _ _ _| |_ | . > ___ _| |_
# \__ \| | || . \| . \/ . \| '_> | | | . \/ . \ | |
# <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_|
# |_| |_|
#
# SupportBot created by Emerald Services
# Installed with MIT License
#
# Discord Support: https://emeraldsrv.dev/discord
# Community Resources: https://emeraldsrv.dev/resources
# -------------------------------
# Ticket Panel Configuration
# -------------------------------
Panel: true
# ----------------------------------------
# Ticket Panel Message Configuration #2b2d31
# ----------------------------------------
Channel: "📗┃tickets"
# The channel used to create the ticket panel, Use command /ticketpanel to generate it.
PanelTitle: "SupportBot"
PanelColour: "#0cc559"
Button:
Text: "Create Ticket"
Emoji: "🎫"
Color: "2"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Red
# 4 - Green
TicketPanel_Description: true
TicketPanel_Thumbnail: false
TicketPanel_Image: true
PanelMessage: "Click on the button to file a `Ticket` and our team will try their best to assist you in the best way we can!"
PanelThumbnail: "https://i.imgur.com/ieeZejl.png"
PanelImage: "https://i.imgur.com/dejQvkg.png"
+1
View File
@@ -0,0 +1 @@
{}
+1
View File
@@ -0,0 +1 @@
{}
+1
View File
@@ -0,0 +1 @@
{}
+3
View File
@@ -0,0 +1,3 @@
{
}
+5
View File
@@ -0,0 +1,5 @@
{
"tickets": [
{}
]
}
+5
View File
@@ -0,0 +1,5 @@
{
"bio": "",
"timezone": "",
"clockedIn": false
}
+4
View File
@@ -0,0 +1,4 @@
{
"id": 0,
"TicketPanelID": "000000000000000000"
}
+9
View File
@@ -0,0 +1,9 @@
const Event = require("../Structures/Event.js");
module.exports = new Event("guildCreate", async (client) => {
console.log(
`\u001b[31m`,
`${client.user.username} is not in the correct server set in your config. Please leave all other servers and restart the bot.`
);
console.log(`\u001b[31m`, `${client.user.username} will now exit.`);
return process.exit(1);
});
+10
View File
@@ -0,0 +1,10 @@
const Event = require("../Structures/Event.js");
module.exports = new Event("guildDelete", async (client) => {
console.log(
`\u001b[31m`,
`${client.user.username} is not in the correct server set in your config. Please join the server and restart the bot.`
);
console.log(`\u001b[31m`, `${client.user.username} will now exit.`);
return process.exit(1);
});
+55
View File
@@ -0,0 +1,55 @@
const Discord = require('discord.js');
const fs = require("fs");
const Event = require("../Structures/Event.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
);
module.exports = new Event("guildMemberAdd", async (client, member, interaction, guild) => {
if (supportbot.Welcome.Enabled) {
const WelcomeChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.Welcome.Channel)
const WelcomeEmbed = new Discord.EmbedBuilder()
.setColor(msgconfig.Welcome.Embed.Colour)
.setTitle(msgconfig.Welcome.Embed.Title)
.setDescription(msgconfig.Welcome.Embed.Message.replace(/%joined_user%/g, member.user))
.setTimestamp();
if (msgconfig.Welcome.Embed.Thumbnail === "BOT") {
WelcomeEmbed.setThumbnail(client.user.displayAvatarURL())
}
if (msgconfig.Welcome.Embed.Thumbnail === "USER") {
WelcomeEmbed.setThumbnail(member.user.displayAvatarURL())
}
if (msgconfig.Welcome.Embed.ImageEnabled) {
WelcomeEmbed.setImage(msgconfig.Welcome.Embed.ImageURL)
}
WelcomeChannel.send({
embeds: [WelcomeEmbed]
})
if (supportbot.Roles.AutoRole.Enabled) {
var role = member.guild.roles.cache.find(role => role.name === supportbot.Roles.AutoRole.Role);
member.roles.add(role);
}
console.log(`\u001b[32m`, `[+]`, `\u001b[33m`, `${member.user.username} joined the server!`)
}
});
+50
View File
@@ -0,0 +1,50 @@
const Discord = require('discord.js');
const fs = require("fs");
const Event = require("../Structures/Event.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
);
module.exports = new Event("guildMemberRemove", async (client, member, interaction, guild) => {
if (supportbot.Leave.Enabled) {
const LeaveChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.Leave.Channel)
const LeaveEmbed = new Discord.EmbedBuilder()
.setColor(msgconfig.Leave.Embed.Colour)
.setTitle(msgconfig.Leave.Embed.Title)
.setDescription(msgconfig.Leave.Embed.Message.replace(/%joined_user%/g, member.user))
.setTimestamp();
if (msgconfig.Leave.Embed.Thumbnail === "BOT") {
LeaveEmbed.setThumbnail(client.user.displayAvatarURL())
}
if (msgconfig.Leave.Embed.Thumbnail === "USER") {
LeaveEmbed.setThumbnail(member.user.displayAvatarURL())
}
if (msgconfig.Leave.Embed.ImageEnabled) {
LeaveEmbed.setImage(msgconfig.Leave.Embed.ImageURL)
}
LeaveChannel.send({
embeds: [LeaveEmbed]
})
console.log(`\u001b[31m`, `[-]`, `\u001b[33m`, `${member.user.username} left the server!`)
}
});
+465
View File
@@ -0,0 +1,465 @@
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Event = require("../Structures/Event.js");
let suggestions;
try {
suggestions = require("../Data/SuggestionData.json");
} catch (error) {
suggestions = {};
}
module.exports = new Event("interactionCreate", async (client, interaction) => {
if (interaction.type === Discord.InteractionType.ApplicationCommand) {
const command = client.commands.find(
(cmd) => cmd.name.toLowerCase() === interaction.commandName
);
if (interaction.user.bot || !interaction.guild) return;
const NotValid = new Discord.EmbedBuilder()
.setDescription(`:x: \`Invalid Command\``)
.setColor(supportbot.Embed.Colours.Error);
if (!command)
return interaction.reply({
embeds: [NotValid],
ephemeral: true,
});
const permission = interaction.member.permissions.has(command.permissions);
const ValidPerms = new Discord.EmbedBuilder()
.setDescription(
"> :x: `Invalid Permissions` Do you have the correct permissions to execute this command?"
)
.setColor(supportbot.Embed.Colours.Error);
if (!permission)
return interaction.reply({
embeds: [ValidPerms],
ephemeral: true,
});
try {
if (command.name === cmdconfig.OpenTicket.Command && supportbot.Ticket.TicketReason) {
const modal = new Discord.ModalBuilder()
.setCustomId("ticketReasonModal")
.setTitle("Ticket Reason")
.addComponents(
new Discord.ActionRowBuilder().addComponents(
new Discord.TextInputBuilder()
.setCustomId("reasonInput")
.setLabel("Reason")
.setStyle(Discord.TextInputStyle.Paragraph)
.setRequired(true)
)
);
await interaction.showModal(modal);
} else {
console.log("\u001b[32m", "[Executed]", "\u001b[37;1m", `${interaction.user.username} has executed ${command.name}`);
await command.run(interaction);
}
} catch (error) {
console.error("Error executing command:", error);
await interaction.reply({
content: "An error occurred while executing the command.",
ephemeral: true,
});
}
}
if (interaction.isModalSubmit()) {
if (interaction.customId === "ticketReasonModal") {
const reason = interaction.fields.getTextInputValue("reasonInput");
interaction.customId = `createticket-${reason}`;
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
if (cmd) {
interaction.reason = reason; // Attach the reason to the interaction object
await cmd.run(interaction);
} else {
console.error("Command not found.");
}
}
}
if (interaction.isStringSelectMenu()) {
if (interaction.customId === "ticketcontrolpanel") {
const selectedOption = interaction.values[0];
const { getRole, getChannel } = interaction.client;
switch (selectedOption) {
case "ticketclose":
const closeCommand = client.commands.get(cmdconfig.CloseTicket.Command);
if (closeCommand) {
await closeCommand.run(interaction);
} else {
console.error("[X] Close Command Not Found");
}
break;
case "archiveticket":
const arcembed = new Discord.EmbedBuilder()
.setDescription(msgconfig.Ticket.TicketArchived)
.setColor(supportbot.Embed.Colours.Success);
const CloseButton = new Discord.ButtonBuilder()
.setCustomId("confirmCloseTicket")
.setLabel(supportbot.Ticket.Close.Confirmation_Button)
.setEmoji(supportbot.Ticket.Close.Confirmation_Emoji)
.setStyle(supportbot.Ticket.Close.Confirmation_Style);
const unarchiveButton = new Discord.ButtonBuilder()
.setCustomId("unarchiveTicket")
.setLabel(supportbot.Buttons.Tickets.Unarchive)
.setEmoji(supportbot.Buttons.Tickets.Unarchive_Emoji)
.setStyle(supportbot.Buttons.Tickets.Unarchive_Style);
const ArchivedOptions = new Discord.ActionRowBuilder()
.addComponents(CloseButton, unarchiveButton);
await interaction.channel.send({
embeds: [arcembed],
components: [ArchivedOptions],
});
await interaction.channel.setArchived(true);
break;
case "lockticket":
const lockembed = new Discord.EmbedBuilder()
.setDescription(msgconfig.Ticket.TicketLocked)
.setColor(supportbot.Embed.Colours.Success);
await interaction.channel.send({
embeds: [lockembed],
components: [],
ephemeral: true,s
});
await interaction.channel.setLocked(true);
break;
case "enableinvites":
await handleInvites(interaction, true);
break;
case "disableinvites":
await handleInvites(interaction, false);
break;
}
}
}
if (interaction.isButton()) {
if (interaction.customId === "unarchiveTicket") {
await interaction.channel.setArchived(false);
const unrcembed = new Discord.EmbedBuilder()
.setDescription(msgconfig.Ticket.TicketUnarchived)
.setColor(supportbot.Embed.Colours.Success);
await interaction.update({
embeds: [unrcembed],
components: [],
});
}
if (interaction.customId === "createticket") {
if (supportbot.Ticket.TicketReason) {
const modal = new Discord.ModalBuilder()
.setCustomId("ticketReasonModal")
.setTitle("Ticket Reason")
.addComponents(
new Discord.ActionRowBuilder().addComponents(
new Discord.TextInputBuilder()
.setCustomId("reasonInput")
.setLabel("Reason")
.setStyle(Discord.TextInputStyle.Paragraph)
.setRequired(true)
)
);
await interaction.showModal(modal);
} else {
try {
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
if (!cmd) return;
await cmd.run(interaction);
} catch (error) {
console.error("Error executing the ticket command:", error);
await interaction.reply({
content: "An error occurred while creating the ticket.",
ephemeral: true,
});
}
}
}
if (interaction.customId === "openticket") {
if (supportbot.Ticket.TicketReason) {
const modal = new Discord.ModalBuilder()
.setCustomId("ticketReasonModal")
.setTitle("Ticket Reason")
.addComponents(
new Discord.ActionRowBuilder().addComponents(
new Discord.TextInputBuilder()
.setCustomId("reasonInput")
.setLabel("Reason")
.setStyle(Discord.TextInputStyle.Paragraph)
.setRequired(true)
)
);
await interaction.showModal(modal);
} else {
try {
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
if (!cmd) return;
await cmd.run(interaction);
} catch (error) {
console.error(error);
}
}
}
if (interaction.customId.startsWith("claimticket-")) {
const ticketChannelId = interaction.customId.split("-")[1];
const ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
if (!ticketChannel) {
return interaction.reply({
content: "Ticket channel not found.",
ephemeral: true,
});
}
const { getRole, getChannel } = interaction.client;
const Staff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
const RolePerms = new Discord.EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
if (!Staff || !Admin) {
return interaction.reply({
embeds: [RolePerms],
ephemeral: true,
});
}
const NoPermsClaim = new Discord.EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.NoPermsToClaimTitle)
.setDescription(
msgconfig.Ticket.ClaimTickets.NoPermsToClaim.replace("%channel%", ticketChannel.name)
)
.setColor(supportbot.Embed.Colours.Error);
if (!interaction.member.roles.cache.has(Staff.id) && !interaction.member.roles.cache.has(Admin.id)) {
return interaction.reply({
embeds: [NoPermsClaim],
ephemeral: true,
});
}
await ticketChannel.members.add(interaction.user.id);
const pingclaimedstaff = await ticketChannel.send(`<@${interaction.user.id}>`);
setTimeout(() => {
pingclaimedstaff.delete();
}, 2000);
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const ticketIndex = TicketData.tickets.findIndex((t) => t.id === ticketChannelId);
if (ticketIndex !== -1) {
TicketData.tickets[ticketIndex].claimedBy = interaction.user.id;
TicketData.tickets[ticketIndex].claimedAt = new Date().toISOString();
fs.writeFileSync("./Data/TicketData.json", JSON.stringify(TicketData, null, 4));
}
const claimMessage = await interaction.message.fetch();
const claimedEmbed = new Discord.EmbedBuilder(claimMessage.embeds[0].data)
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
.setDescription(
msgconfig.Ticket.ClaimTickets.ClaimMessage_Edit.replace("%user%", interaction.user.id).replace("%channel%", ticketChannel.id)
)
.setColor(supportbot.Embed.Colours.Success);
const successfullyClaimed = new Discord.EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
.setDescription(msgconfig.Ticket.ClaimTickets.Claimed.replace("%channel%", ticketChannel.id))
.setColor(supportbot.Embed.Colours.Success);
await claimMessage.edit({ embeds: [claimedEmbed], components: [] });
await interaction.reply({
embeds: [successfullyClaimed],
ephemeral: true,
});
}
// SUGGESTION INTERACTIONS [START]
if (
interaction.customId === "upvote" ||
interaction.customId === "downvote" ||
interaction.customId === "removevote"
) {
const suggestion = suggestions[interaction.message.id];
if (!suggestion)
return interaction.reply({ content: "Suggestion not found.", ephemeral: true });
const userId = interaction.user.id;
const hasUpvoted = suggestion.upvotes.includes(userId);
const hasDownvoted = suggestion.downvotes.includes(userId);
if (interaction.customId === "upvote") {
if (hasUpvoted) {
suggestion.upvotes = suggestion.upvotes.filter((id) => id !== userId);
} else {
suggestion.upvotes.push(userId);
if (hasDownvoted) {
suggestion.downvotes = suggestion.downvotes.filter((id) => id !== userId);
}
}
} else if (interaction.customId === "downvote") {
if (hasDownvoted) {
suggestion.downvotes = suggestion.downvotes.filter((id) => id !== userId);
} else {
suggestion.downvotes.push(userId);
if (hasUpvoted) {
suggestion.upvotes = suggestion.upvotes.filter((id) => id !== userId);
}
}
} else if (interaction.customId === "removevote") {
suggestion.upvotes = suggestion.upvotes.filter((id) => id !== userId);
suggestion.downvotes = suggestion.downvotes.filter((id) => id !== userId);
}
fs.writeFileSync("./Data/SuggestionData.json", JSON.stringify(suggestions, null, 2));
const upvoteCount = suggestion.upvotes.length;
const downvoteCount = suggestion.downvotes.length;
const updatedEmbed = new Discord.EmbedBuilder(interaction.message.embeds[0].data).setFields([
{ name: "Suggestion", value: suggestion.suggestion, inline: true },
{ name: "From", value: `<@${suggestion.author}>` },
{
name: `${supportbot.Suggestions.UpvoteEmoji} ${supportbot.Suggestions.UpvoteTitle}`,
value: `${upvoteCount}`,
inline: true,
},
{
name: `${supportbot.Suggestions.DownvoteEmoji} ${supportbot.Suggestions.DownvoteTitle}`,
value: `${downvoteCount}`,
inline: true,
},
]);
await interaction.update({ embeds: [updatedEmbed] });
}
}
async function handleInvites(interaction, enable) {
if (supportbot.Ticket.Invites.StaffOnly) {
const { getRole, getChannel } = interaction.client;
const SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin) {
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
}
const NoPerms = new Discord.EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
!interaction.member.roles.cache.has(Admin.id)
) {
return interaction.reply({ embeds: [NoPerms] });
}
}
await interaction.channel.setInvitable(enable);
const message = enable ? msgconfig.Ticket.EnableInvites : msgconfig.Ticket.DisableInvites;
const embed = new Discord.EmbedBuilder().setDescription(message).setColor(supportbot.Embed.Colours.General);
await interaction.reply({
embeds: [embed],
ephemeral: true,
});
}
// Modal submission handler for editing profile
if (interaction.type === Discord.InteractionType.ModalSubmit && interaction.customId === "editProfileModal") {
const userId = interaction.user.id;
const profilePath = `./Data/Profiles/${userId}.json`;
let profileData;
if (fs.existsSync(profilePath)) {
profileData = JSON.parse(fs.readFileSync(profilePath, "utf8"));
} else {
profileData = {
bio: "",
timezone: "",
clockedIn: false,
};
}
try {
const newBio = interaction.fields.getTextInputValue("bio");
const newTimezone = interaction.fields.getTextInputValue("timezone");
profileData.bio = newBio;
profileData.timezone = newTimezone;
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
const updatedProfileEmbed = new Discord.EmbedBuilder()
.setTitle(`${interaction.user.username}'s Profile`)
.setColor(supportbot.Embed.Colours.General)
.setThumbnail(interaction.user.displayAvatarURL())
.addFields(
{ name: "Bio", value: newBio || "No bio set.", inline: false },
{ name: "Timezone", value: newTimezone || "No timezone set.", inline: true }
);
if (profileData.clockedIn !== undefined) {
updatedProfileEmbed.addFields({
name: "Clocked In Status",
value: profileData.clockedIn ? "✅ Clocked In" : "❌ Clocked Out",
inline: true,
});
}
await interaction.reply({ embeds: [updatedProfileEmbed], ephemeral: true });
} catch (error) {
console.error("Failed to update profile data: ", error);
await interaction.reply({
content: "There was an error while updating your profile. Please try again later.",
ephemeral: true,
});
}
}
});
+166
View File
@@ -0,0 +1,166 @@
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const axios = require("axios");
const { OpenAI } = require('openai');
// Load configuration files with validation
function loadConfig(path) {
try {
return yaml.load(fs.readFileSync(path, "utf8"));
} catch (error) {
console.error(`Error loading config file at ${path}:`, error);
throw error;
}
}
const supportbotai = yaml.load(fs.readFileSync("./Configs/supportbot-ai.yml"));
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
// Validate configuration values
function validateConfig(config, keys) {
keys.forEach(key => {
if (!config[key]) {
throw new Error(`Missing configuration key: ${key}`);
}
});
}
const CHANNELS = [supportbotai.Channels.AIChannel];
// Initialize Discord client
const client = new Discord.Client({
intents: ['Guilds', 'GuildMembers', 'GuildMessages']
});
// Load custom Event structure
const Event = require("../Structures/Event.js");
// Initialize OpenAI client
const openai = new OpenAI({
apiKey: supportbotai.General.OpenAI_Key,
});
const PASTEBIN_API_KEY = supportbotai.General.PastebinAPI_Key;
const PASTEBIN_API_URL = supportbotai.General.PastebinAPI_URL;
// Function to create a paste on Pastebin
async function createPaste(content) {
try {
const response = await axios.post(PASTEBIN_API_URL, new URLSearchParams({
api_dev_key: PASTEBIN_API_KEY,
api_option: 'paste',
api_paste_code: content,
api_paste_private: 1, // 0 = public, 1 = unlisted, 2 = private
api_paste_expire_date: '1D', // Expire in 1 day
api_paste_format: 'text'
}));
return response.data;
} catch (error) {
console.error('Pastebin Error:', error);
throw error;
}
}
// Event handler for message creation
module.exports = new Event("messageCreate", async (client, message) => {
if (message.author.bot || !message.guild) return;
if (!CHANNELS.includes(message.channelId) && !message.mentions.users.has(client.user.id)) return;
if (supportbotai.Enabled) {
const sendTypingInterval = setInterval(() => {
message.channel.sendTyping();
}, 5000);
let conversation = [{
role: "system",
content: "SupportBot is your friendly neighbourhood support bot."
}];
let prevMessages = await message.channel.messages.fetch({ limit: 10 });
prevMessages = prevMessages.reverse().filter(msg => !msg.author.bot || msg.author.id === client.user.id);
prevMessages.forEach((msg) => {
const username = msg.author.username.replace(/\s+/g, '_').replace(/[^\w\s]/gi, '');
conversation.push({
role: msg.author.id === client.user.id ? "assistant" : "user",
name: username,
content: msg.content,
});
});
try {
const response = await openai.chat.completions.create({
model: supportbotai.General.Model,
messages: conversation,
max_tokens: supportbotai.General.Tokens,
});
clearInterval(sendTypingInterval);
if (response.choices && response.choices.length > 0) {
const replyContent = response.choices[0].message.content;
const SupportBotAI = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(replyContent)
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
if (replyContent.length > 2000) {
const pasteLink = await createPaste(replyContent);
const SupportBotAIPastebin = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.MessageTooLong.replace("{pastebin}", pasteLink))
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [SupportBotAIPastebin] });
} else {
message.reply({ embeds: [SupportBotAI] });
}
} else {
const SupportBotAIErrorResponse = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.ErrorResponse)
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [SupportBotAIErrorResponse], ephemeral: true });
}
} catch (error) {
clearInterval(sendTypingInterval);
const SupportBotAIErrorResponse = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.OpenAIError)
.setColor(supportbot.Embed.Colours.Error)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
console.error('OpenAI Error:', error);
message.reply({ embeds: [SupportBotAIErrorResponse], ephemeral: true });
}
}
if (supportbotai.Enabled === false) {
const AIDisabled = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.AIDisabled)
.setColor(supportbot.Embed.Colours.Error)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [AIDisabled], ephemeral: true })
return;
}
});
+147
View File
@@ -0,0 +1,147 @@
// SupportBot | Emerald Services
// Ready Event
const fs = require("fs");
const Discord = require("discord.js");
const { Client, GatewayIntentBits, ActivityType } = require('discord.js');
const client = new Discord.Client({intents: 32767})
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const panelconfig = yaml.load(
fs.readFileSync("./Configs/ticket-panel.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
);
const Event = require("../Structures/Event.js");
let chan1 = client.channels.cache.get(panelconfig.Channel);
module.exports = new Event("ready", async (client, interaction) => {
const { getRole, getChannel, getCategory } = client;
if (supportbot.Activity.Type === "Playing", "playing") {
client.user.setPresence({
activities: [{ name: supportbot.Activity.Status, type: Discord.ActivityType.Playing }],
status: supportbot.Activity.Type,
});
}
if (supportbot.Activity.Type === "Watching", "watching") {
client.user.setPresence({
activities: [{ name: supportbot.Activity.Status, type: Discord.ActivityType.Watching }],
status: supportbot.Activity.Type,
});
}
if (supportbot.Activity.Type === "Listening", "listening") {
client.user.setPresence({
activities: [{ name: supportbot.Activity.Status, type: Discord.ActivityType.Listening }],
status: supportbot.Activity.Type,
});
}
if (supportbot.Activity.Type === "Competing", "competing") {
client.user.setPresence({
activities: [{ name: supportbot.Activity.Status, type: Discord.ActivityType.Competing }],
status: supportbot.Activity.Type,
});
}
console.log(`\u001b[33m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(` `);
console.log(`\u001b[31m`, `┏━━━┓╋╋╋╋╋╋╋╋╋╋╋╋╋┏┓┏━━┓╋╋╋┏┓`);
console.log(`\u001b[31m`, `┃┏━┓┃╋╋╋╋╋╋╋╋╋╋╋╋┏┛┗┫┏┓┃╋╋┏┛┗┓`);
console.log(`\u001b[31m`, `┃┗━━┳┓┏┳━━┳━━┳━━┳┻┓┏┫┗┛┗┳━┻┓┏┛`);
console.log(`\u001b[31m`, `┗━━┓┃┃┃┃┏┓┃┏┓┃┏┓┃┏┫┃┃┏━┓┃┏┓┃┃`);
console.log(`\u001b[31m`, `┃┗━┛┃┗┛┃┗┛┃┗┛┃┗┛┃┃┃┗┫┗━┛┃┗┛┃┗┓`);
console.log(`\u001b[31m`, `┗━━━┻━━┫┏━┫┏━┻━━┻┛┗━┻━━━┻━━┻━┛`);
console.log(`\u001b[31m`, `┗╋╋╋╋╋╋╋┃┃╋┃┃`);
console.log(`\u001b[31m`, `╋╋╋╋╋╋╋┗┛╋┗┛`);
console.log(` `);
console.log(`\u001b[33m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(` `);
console.log(`\u001b[33m`, `${supportbot.General.Name} | [${supportbot.SupportBot_Version}]`, `\u001b[32m`, `Connected to Discord`,);
console.log("\u001b[32m", "SupportBot created by Emerald Development ");
console.log(` `);
console.log(`\u001b[33m`, `――――――――――――――――― [Links] ――――――――――――――――――`);
console.log("\u001b[32m", "Discord: https://dsc.gg/emerald-dev");
console.log("\u001b[32m", "Website: https://emeraldsrv.com");
console.log("\u001b[32m", "Community: https://community.emeraldsrv.com");
console.log("\u001b[32m", "Documentation: https://docs.emeraldsrv.com");
console.log(` `);
console.log(`\u001b[33m`, `――――――――――――――――― [Invite] ――――――――――――――――――`);
console.log("\u001b[32m", `Invite URL: https://discord.com/api/oauth2/authorize?client_id=${client.user.id}&permissions=8&scope=bot%20applications.commands`);
console.log(` `);
console.log(`\u001b[33m`, `――――――――――――――――― [Config Check] ――――――――――――――――――`);
console.log("\u001b[32m", "Config initialization...");
const roles = [
supportbot.Roles.StaffMember.Admin,
supportbot.Roles.StaffMember.Staff,
supportbot.Roles.ModRoles.Blacklisted,
supportbot.Roles.ModRoles.Muted
];
supportbot.Departments.forEach((department) => roles.push(department.role));
if (supportbot.Roles.AutoRole.Role) roles.push(supportbot.Roles.AutoRole.Role);
const channels = [
supportbot.Suggestions.Channel,
supportbot.Ticket.Log.TicketLog,
supportbot.Ticket.Log.TranscriptLog,
panelconfig.Channel,
supportbot.Welcome.Channel,
supportbot.Leave.Channel,
supportbot.Translate.Log
];
//const categories = [supportbot.TicketCategory];
if (!channels) {
console.log("\u001b[31m", `[MISSING CHANNEL]`, `\u001b[37;1m`, `${channels}`, "\u001b[31m", `channel not found. Please check your config file.`);
return;
}
// else {
// console.log(`\u001b[32m`, `[CHANNEL LOCATED]`, `\u001b[37;1m`, `${channels}`, `\u001b[32;1m`, `channel has been found.`);
// }
const missingC = [];
const missingR = [];
const missingCat = [];
for (let r of roles) {
const find = await getRole(r, client.guilds.cache.first());
if (!find) missingR.push(r);
}
// for (let cat of categories) {
// const find = await getCategory(cat, client.guilds.cache.first());
// if (!find) missingCat.push(cat);
// }
const missingRoles = await Promise.all(roles.map(role => getRole(role, client.guilds.cache.first())));
const missingChannels = await Promise.all(channels.map(channel => getChannel(channel, client.guilds.cache.first())));
if (missingRoles.some(role => !role)) {
console.log("\u001b[31m", `Missing roles in your server configuration: ${missingRoles.filter(role => !role).join(', ')}`);
}
if (missingChannels.some(channel => !channel)) {
console.log("\u001b[31m", `Missing channels in your server configuration: ${missingChannels.filter(channel => !channel).join(', ')}`);
}
console.log("\u001b[32m", "Configs initialized, No problems were detected.");
console.log(` `);
});
+2 -2
View File
@@ -1,11 +1,11 @@
MIT License
Copyright (c) 2021 Emerald Services
Copyright (c) 2024 Emerald Services
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Executable → Regular
+96 -10
View File
@@ -1,10 +1,96 @@
> #### SupportBot
>
> - SupportBot is a free to use discord ticket system that is highly customisable to your own brand,
Why use a branded ticket bot when you have the ability to match your ticket bot with your servers name.
>
> - Our Support team is over at [Discord](https://discord.com/invite/jspKFcE) ready to assist with any questions, concerns or setup information regarding SupportBot.
>
> - [Download via Polymart](https://polymart.org/resource/supportbot-1-discord-ticket-bot.518)
> - [Download via MC-Market](https://www.mc-market.org/resources/8940/)
<h1 align="center">
<br>
<a href="https://github.com/Emerald-Services/SupportBot"><img src="https://i.imgur.com/cuadAYv.png"></a>
<br>
SupportBot
<br>
</h1>
<div align="center">
<a href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/badge/license-MIT-green?style=for-the-badge" alt="shield.png">
</a>
<a href="https://github.com/discordjs">
<img src="https://img.shields.io/badge/discord.js-v13.6.x-blue.svg?style=for-the-badge&logo=javascript.svg" alt="shield.png">
</a>
<a href="https://github.com/nodejs/node">
<img src="https://img.shields.io/badge/node.js-v16.14.x-green.svg?style=for-the-badge&logo=node" alt="shield.png">
</a>
<a href="https://github.com/Emerald-Services/SupportBot/releases">
<img src="https://img.shields.io/github/downloads/Emerald-Services/SupportBot/total?style=for-the-badge" alt="shield.png">
</a>
## Supported Versions
| SupportBot | Node.JS | Discord.JS | Supported |
|------------|---------|------------|------------|
| 8.x | 20.x | 14.x. | ✅ Yes
| 7.7.3 | 16.x | 13.x. | ✅ Yes
| 7.x | 16.x | 13.x. | ❌ No
| 6.x | 14.x | 13.x. | ❌ No
| 5.x | 12.x | 13.x. | ❌ No
| 4.x | 11.x | 13.x. | ❌ No
| Older | 10.x | 13.x. | ❌ No
</div>
<p align="center">
<a href="https://emeraldsrv.com/">Website</a>
•
<a href="https://github.com/Emerald-Services/SupportBot/wiki">Wiki</a>
<br>
<a href="#about">About</a>
•
<a href="#support">Support</a>
•
<a href="#license">License</a>
•
<a href="https://github.com/Emerald-Services/SupportBot/wiki/Third-Party-Developer">Third-Party</a>
•
<a href="#contributors">Contributors</a>
</p>
## About
SupportBot is an Open-Source discord bot built with [discord.js](https://github.com/discordjs/discord.js). It's primarily focused to help servers organise and manage their support system in a unique way with full customisation to match your brand.
## Support
<a href="https://emeraldsrv.com/discord">
<img alt="Discord" src="https://img.shields.io/discord/597779408295821323?logo=discord&logoColor=white&style=for-the-badge">
</a>
## License
Released under the [MIT](https://opensource.org/licenses/MIT) license.
## Third-Party
- [Official addons repository](https://github.com/Emerald-Services/Addons/)
- [Syphers Addons](https://github.com/SypherRed/SB_Addons_Unofficial)
- [BuiltByBit](https://builtbybit.com/supportbot)
- [Polymart](https://polymart.org/resource/supportbot-1-discord-ticket-bot.518)
## Contributors
<a href="https://github.com/Emerald-Services/SupportBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=Emerald-Services/SupportBot">
</a>
## Hosting
You can use our [Pterodactyl egg](https://github.com/Emerald-Services/Pterodactyl-Egg) to host it on your own panel. We currently don't offer hosting for you, altough we might add this in the future.
If you don't know how to install pterodactyl, you could always host it on replit:
[![Run on Repl.it](https://repl.it/badge/github/ItsNyoty/IKI-bot)]([https://repl.it/github/ItsNyoty/iki](https://repl.it/github/Emerald-Services/SupportBot
)
+20
View File
@@ -0,0 +1,20 @@
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 7.7.2 | :white_check_mark: |
| 7.7.1 | :white_check_mark: |
| < 4.0 | :x: |
## Reporting a Vulnerability
Use this section to tell people how to report a vulnerability.
Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.
+21
View File
@@ -0,0 +1,21 @@
// SupportBot | Emerald Services
// Addon Structure
class Command {
constructor(options) {
this.name = options.name;
this.description = options.description;
this.permissions = options.permissions;
this.options = options.options || [];
this.run = options.run;
this.defaultPermission = true;
}
}
class Event {
constructor(event, run) {
this.event = event;
this.run = run;
}
}
module.exports = { Command, Event };
+190
View File
@@ -0,0 +1,190 @@
const fs = require("fs");
const Discord = require("discord.js");
const { GatewayIntentBits, Partials } = require('discord.js');
const yaml = require("js-yaml");
const { Command, Event } = require('./Addon.js'); // Adjust the path as needed
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
class Client extends Discord.Client {
constructor() {
super({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages
],
partials: [Partials.Channel]
});
this.commands = new Discord.Collection();
}
async getChannel(channel, guild) {
if (!channel) return null; // Add check for undefined channel
return guild.channels.cache.find(
(c) =>
(c.type === Discord.ChannelType.GuildText || c.type === Discord.ChannelType.GuildNews) &&
(c.id === channel || (c.name && c.name.toLowerCase() === channel.toLowerCase()))
);
}
async getRole(role, guild) {
if (!role) return null; // Add check for undefined role
return guild.roles.cache.find(
(r) => r.id === role || (r.name && r.name.toLowerCase() === role.toLowerCase())
);
}
async getCategory(category, guild) {
if (!category) return null; // Add check for undefined category
return guild.channels.cache.find(
(c) =>
c.type === Discord.ChannelType.GuildCategory &&
(c.id === category || (c.name && c.name.toLowerCase() === category.toLowerCase()))
);
}
async start(token) {
let tempCommandFiles = fs.readdirSync("./Commands").filter((file) => file.endsWith(".js"));
if (cmdconfig.Suggestion.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "suggest.js");
}
if (cmdconfig.Help.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "help.js");
}
if (cmdconfig.Info.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "info.js");
}
if (cmdconfig.OpenTicket.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "ticket.js");
}
if (cmdconfig.CloseTicket.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "close.js");
}
if (cmdconfig.Embed.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "embed.js");
}
if (cmdconfig.Translate.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "translate.js");
}
if (cmdconfig.UserInfo.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "userinfo.js");
}
if (cmdconfig.Ping.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
}
if (cmdconfig.AddUser.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "addUser.js");
}
if (cmdconfig.RemoveUser.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "removeUser.js");
}
if (cmdconfig.ForceAddUser.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "forceaddUser.js");
}
if (cmdconfig.Profile.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "Profile.js");
}
const commandFiles = tempCommandFiles;
const commands = commandFiles.map((file) => require(`../Commands/${file}`));
// Load main commands
console.log(`\u001b[33m`, "――――――――――――――――――――――――――――――――――――――――――――");
commands.forEach((cmd) => {
console.log(`\u001b[32m`, `[CMD]`, `\u001b[37;1m`, `${cmd.name}`, `\u001b[32;1m`, "Loaded");
this.commands.set(cmd.name, cmd);
});
// Load addon commands and events
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
if (supportbot.General.Addons.Enabled) {
const addonFiles = fs.readdirSync("./Addons").filter((file) => file.endsWith(".js"));
const addons = addonFiles.map((file) => {
const addon = require(`../Addons/${file}`);
addon.name = file.split(".")[0];
return addon;
});
// Addons
console.log(" ");
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
addons.forEach((addon) => {
console.log(
`\u001b[32m`,
`[ADDON]`,
`\u001b[37;1m`,
`${addon.name}`,
`\u001b[32;1m`,
"Loaded"
);
if (addon instanceof Command) {
this.commands.set(addon.name, addon);
}
if (addon.events && Array.isArray(addon.events)) {
addon.events.forEach((event) => {
if (event instanceof Event) {
this.on(event.event, (...args) => event.run(this, ...args));
}
});
}
});
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
}
// Register Slash Commands
this.once("ready", async () => {
await this.guilds.cache.first()?.commands.set(this.commands);
console.log(
"\u001b[32m",
`[SUCCESS]`,
`\u001b[37;1m`,
`Slash Commands Registered for ${this.guilds.cache.first().name}`
);
});
console.log(" ");
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
fs.readdirSync("./Events").filter((file) => file.endsWith(".js")).forEach((file) => {
const event = require(`../Events/${file}`);
console.log(`\u001b[32m`, `[EVENT]`, `\u001b[37;1m`, `${event.event}`, `\u001b[32;1m`, "Loaded");
this.on(event.event, (...args) => event.run(this, ...args));
});
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
if (process.argv[2] !== "test") {
await this.login(token);
} else {
console.log(
`\u001b[31;1m`,
"RUNNING IN TEST MODE, IF NOT INTENDED, PLEASE USE npm start"
);
}
}
}
module.exports = Client;
+14
View File
@@ -0,0 +1,14 @@
// SupportBot | Emerald Services
// Command Structure
class Command {
constructor(options) {
this.name = options.name;
this.description = options.description;
this.permissions = options.permissions || [];
this.options = options.options || [];
this.run = options.run;
this.defaultPermission = true;
}
}
module.exports = Command;
+10
View File
@@ -0,0 +1,10 @@
// SupportBot | Emerald Services
// Event Structure
class Event {
constructor(event, run) {
this.event = event;
this.run = run;
}
}
module.exports = Event;
+47
View File
@@ -0,0 +1,47 @@
// SupportBot | Emerald Services
// Ticket ID Structure
const fs = require("fs");
class TicketNumberID {
static async pad() {
let num = await this.get();
let n = num + "";
await this.set(num + 1);
return n.length >= 4 ? n : new Array(4 - n.length + 1).join("0") + n;
}
static async get() {
let ticketnumberID = await JSON.parse(
fs.readFileSync("./Data/ticket-panel-id.json", "utf8")
);
if (!ticketnumberID.id) {
return this.set(0);
} else {
return ticketnumberID.id;
}
}
static async set(value) {
let ticketnumberID = await JSON.parse(
fs.readFileSync("./Data/ticket-panel-id.json", "utf8")
);
ticketnumberID.id = value;
fs.writeFileSync(
"./Data/ticket-panel-id.json",
JSON.stringify(ticketnumberID, null, 4),
(err) => {
if (err) console.error(err);
}
);
return value;
}
static async reset() {
return await this.set(0);
}
}
module.exports = TicketNumberID;
-20
View File
@@ -1,20 +0,0 @@
// SupportBot, Created by Emerald Services
// Help Command
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
// location for the addons configuration, to keep it simple we generate a settings folder within the addons directory.
const example = yaml.load(fs.readFileSync('./addons/settings/exampleaddon.yml', 'utf8'));
module.exports = {
name: example.ExampleAddonCommand,
description: example.ExampleAddonDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
message.channel.send(example.ExampleAddonMessage)
}
};
BIN
View File
Binary file not shown.
-9
View File
@@ -1,9 +0,0 @@
#
# SupportBot, Created by Emerald Services
# Example Addon
#
ExampleAddonCommand: "exampleaddon"
ExampleAddonDesc: "This is the default/example addon for SupportBot."
ExampleAddonMessage: "> :white_check_mark: This is the **default** addon for SupportBot. You can download addons from our website, https://emeraldservices.xyz/"
-65
View File
@@ -1,65 +0,0 @@
// SupportBot, Created by Emerald Services
// Add User
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.AddUser,
description: supportbot.AddUserDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.AddUser}!`);
let SupportStaff = message.guild.roles.cache.find(SupportTeam => SupportTeam.name === supportbot.Staff)
let Admins = message.guild.roles.cache.find(AdminUser => AdminUser.name === supportbot.Admin)
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(`${supportbot.IncorrectPerms}\n\nRole Required: \`${supportbot.Staff}\` or \`${supportbot.Admin}\``)
.setColor(supportbot.WarningColour)
if (message.member.roles.cache.has(SupportStaff.id) || message.member.roles.cache.has(Admins.id)) {
if (!message.channel.name.startsWith( `${supportbot.TicketChannel}-` )) {
const Exists = new Discord.MessageEmbed()
.setTitle("No Ticket Found!")
.setDescription(`${supportbot.NoValidTicket}`)
.setColor(supportbot.WarningColour);
message.channel.send({ embed: Exists });
return;
}
let rUser = message.guild.member(message.mentions.users.first() || message.guild.members.cache.get(args[0]));
const UserNotExist = new Discord.MessageEmbed()
.setTitle("User Not Found!")
.setDescription(`${supportbot.UserNotFound}\n\nTry Again:\`${supportbot.Prefix}${supportbot.AddUser} <user#0000>\``)
.setColor(supportbot.ErrorColour)
if (!rUser) return message.channel.send({ embed: UserNotExist });
message.channel.updateOverwrite(rUser, {
VIEW_CHANNEL: true,
CREATE_INVITE: false,
SEND_MESSAGES: true,
READ_MESSAGES: true
});
const Complete = new Discord.MessageEmbed()
.setTitle("User Added!")
.setDescription(supportbot.AddedUser.replace(/%user%/g, rUser.id))
.setTimestamp()
.setColor(supportbot.EmbedColour)
message.channel.send({ embed: Complete });
} else {
return message.channel.send({ embed: NoPerms });
}
}
};
-73
View File
@@ -1,73 +0,0 @@
// SupportBot, Created by Emerald Services
// Announce
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const { execute } = require("./help");
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.AnnounceCommand,
description: supportbot.AnnounceDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
let locateChannel = message.guild.channels.cache.find(AnnouncementChannel => AnnouncementChannel.name === supportbot.AnnouncementChannel);
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.AnnounceCommand}!`);
const errornochannel = new Discord.MessageEmbed()
.setTitle("Invalid Channel")
.setDescription(`${supportbot.InvalidChannel}\n\nChannel Required: \`${supportbot.AnnouncementChannel}`)
.setColor(supportbot.ErrorColour);
if(!locateChannel) return message.channel.send({ embed: errornochannel });
let Admins = message.guild.roles.cache.find(adminRole => adminRole.name === supportbot.Admin);
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(`${supportbot.IncorrectPerms}\n\nRole Required: \`${Admins.name}\``)
.setColor(supportbot.WarningColour)
if (!message.member.roles.cache.has(Admins.id))
return message.channel.send({ embed: NoPerms });
const embed = new Discord.MessageEmbed()
.setDescription(`> **${supportbot.AnnouncementStarter}**`)
.setColor(supportbot.EmbedColour)
message.channel.send({ embed: embed });
let announcement = []
message.channel.awaitMessages(response => response.content.length > 2, {
max: 1,
time: 500000,
errors: ['time'],
}).then((collected) => {
announcement.push(collected.map(r => r.content));
locateChannel.send('@everyone')
const AnnouncementEmbed = new Discord.MessageEmbed()
.setTitle(supportbot.AnnouncementTitle)
.setThumbnail(supportbot.AnnouncementIcon)
.setDescription(announcement)
.setColor(supportbot.EmbedColour)
.setFooter(supportbot.EmbedFooter, message.author.displayAvatarURL());
locateChannel.send({ embed: AnnouncementEmbed }).then(async function(msg) {
const AnnouncementComplete = new Discord.MessageEmbed()
.setColor(supportbot.SuccessColour)
.setDescription(`:white_check_mark: You have successfully created an announcement. <#${locateChannel.id}>`)
message.channel.send({ embed: AnnouncementComplete })
})
});
}
};
-53
View File
@@ -1,53 +0,0 @@
// SupportBot, Created by Emerald Services
// Say Command
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const { execute } = require("./help");
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.BotSay,
description: supportbot.BotSayDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
let SupportStaff = message.guild.roles.cache.find(adminRole => adminRole.name === supportbot.Staff);
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.BotSay}!`);
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(`${supportbot.IncorrectPerms}\n\nRole Required: \`${SupportStaff.name}\``)
.setColor(supportbot.WarningColour)
if (!message.member.roles.cache.has(SupportStaff.id))
return message.channel.send({ embed: NoPerms });
const embed = new Discord.MessageEmbed()
.setDescription(`> **What would you like me to say!**`)
.setColor(supportbot.EmbedColour)
message.channel.send({ embed: embed });
let announcement = []
message.channel.awaitMessages(response => response.content.length > 2, {
max: 1,
time: 500000,
errors: ['time'],
}).then((collected) => {
announcement.push(collected.map(r => r.content));
const AnnouncementEmbed = new Discord.MessageEmbed()
.setDescription(announcement)
.setColor(supportbot.EmbedColour)
message.channel.send({ embed: AnnouncementEmbed })
})
}
};
-149
View File
@@ -1,149 +0,0 @@
// SupportBot, Created by Emerald Services
// Close Command
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const { execute } = require("./help");
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.CloseTicket,
description: supportbot.CloseTicketDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.CloseTicket}!`);
if (!message.channel.name.startsWith( `${supportbot.TicketChannel}-` )) {
const Exists = new Discord.MessageEmbed()
.setTitle("No Ticket Found!")
.setDescription(`${supportbot.NoValidTicket}`)
.setColor(supportbot.WarningColour);
message.channel.send({ embed: Exists });
return;
}
if (supportbot.CloseConfirmation === "true") {
const CloseTicketRequest = new Discord.MessageEmbed()
.setTitle(`**${supportbot.ClosingTicket}**`)
.setDescription(`Please confirm by repeating the following word.. \`${supportbot.ClosingConfirmation_Word}\` `)
.setColor(supportbot.EmbedColour);
message.channel.send(CloseTicketRequest).then(m => {
message.channel.awaitMessages( response => response.content.toLowerCase() === supportbot.ClosingConfirmation_Word, {
max: 1,
time: 20000,
errors: [ 'time' ],
}).then( collected => {
let logChannel = message.guild.channels.cache.find(channel => channel.name === supportbot.TranscriptLog);
let user = message.author;
let reason = args.join(" ") || "No Reason Provided.";
let name = message.channel.name;
let ticketChannel = message.channel;
message.channel.send(`**${supportbot.ClosingTicket}**`)
.then(() => {
const logEmbed = new Discord.MessageEmbed()
.setTitle(supportbot.TranscriptTitle)
.setColor(supportbot.EmbedColour)
.setFooter(supportbot.EmbedFooter)
.addField("Closed By", message.author.tag)
.addField("Reason", reason);
message.channel.messages.fetch({ limit: 100 }).then( msgs => {
let txt = '';
msgs = msgs.sort( ( a, b ) => a.createdTimestamp - b.createdTimestamp );
txt += `${message.guild.name}\n`;
txt += `#${ticketChannel.name}\n`;
txt += `${msgs.size} messages\n\n\n`;
msgs.forEach( msg => {
if ( msg.content ) {
txt += `----- ${msg.author.tag} at ${msg.createdAt}\n`;
txt += `${msg.content}\n`;
txt += `-----\n\n`;
}
});
logChannel.send(logEmbed).catch(err => {
message.reply(err)
})
logChannel.send( new Discord.MessageAttachment( Buffer.from( txt ), `${name}.txt` ) );
message.channel.delete();
})
})
})
}).catch( () => {
m.edit('The request to close the ticket has timed out.').then( m2 => m2.delete( 3000 ) );
});
}
if (supportbot.CloseConfirmation === "false") {
let logChannel = message.guild.channels.cache.find(channel => channel.name === supportbot.TranscriptLog);
let user = message.author;
let reason = args.join(" ") || "No Reason Provided.";
let name = message.channel.name;
let ticketChannel = message.channel;
message.channel.send(`**${supportbot.ClosingTicket}**`)
.then(() => {
const logEmbed = new Discord.MessageEmbed()
.setTitle(supportbot.TranscriptTitle)
.setColor(supportbot.EmbedColour)
.setFooter(supportbot.EmbedFooter)
.addField("Closed By", message.author.tag)
.addField("Reason", reason);
message.channel.messages.fetch({ limit: 100 }).then( msgs => {
let txt = '';
msgs = msgs.sort( ( a, b ) => a.createdTimestamp - b.createdTimestamp );
txt += `${message.guild.name}\n`;
txt += `#${ticketChannel.name}\n`;
txt += `${msgs.size} messages\n\n\n`;
msgs.forEach( msg => {
if ( msg.content ) {
txt += `----- ${msg.author.tag} at ${msg.createdAt}\n`;
txt += `${msg.content}\n`;
txt += `-----\n\n`;
}
});
logChannel.send(logEmbed).catch(err => {
message.reply(err)
})
logChannel.send( new Discord.MessageAttachment( Buffer.from( txt ), `${name}.txt` ) );
message.channel.delete();
})
}).catch( () => {
m.edit('The request to close the ticket has timed out.').then( m2 => m2.delete( 3000 ) );
});
}
}
};
-55
View File
@@ -1,55 +0,0 @@
// SupportBot, Created by Emerald Services
// Help Command
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.HelpCommand,
description: supportbot.HelpDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.HelpCommand}!`);
let generalCommands = "";
generalCommands += `**${supportbot.Prefix}${supportbot.HelpCommand}** ${supportbot.HelpDesc}\n`;
generalCommands += `**${supportbot.Prefix}${supportbot.LinksCommand}** ${supportbot.LinkDesc}\n`;
generalCommands += `**${supportbot.Prefix}${supportbot.SuggestCommand}** ${supportbot.SuggestionDesc}\n`;
generalCommands += `**${supportbot.Prefix}${supportbot.PingCommand}** ${supportbot.PingDesc}\n`;
let supportCommands = "";
supportCommands += `**${supportbot.Prefix}${supportbot.NewTicket} [reason]** ${supportbot.NewTicketDesc}\n`
supportCommands += `**${supportbot.Prefix}${supportbot.CloseTicket} [reason]** ${supportbot.CloseTicketDesc}\n`
let staffCommands = "";
staffCommands += `**${supportbot.Prefix}${supportbot.AddUser} <user#0000>** ${supportbot.AddUserDesc}\n`
staffCommands += `**${supportbot.Prefix}${supportbot.RemoveUser} <user#0000>** ${supportbot.RemoveUserDesc}\n`
staffCommands += `**${supportbot.Prefix}${supportbot.BotSay}** ${supportbot.BotSayDesc}\n`
staffCommands += `**${supportbot.Prefix}${supportbot.AnnounceCommand}** ${supportbot.AnnounceDesc}\n`
const HelpCommandEmbed = new Discord.MessageEmbed()
.setTitle(supportbot.Bot_Name)
.setThumbnail(message.author.displayAvatarURL())
.addFields(
{ name: '🖥️ General Commands', value: `${generalCommands}\n`, inline: false },
{ name: '🎫 Support Commands', value: `${supportCommands}\n`, inline: false },
)
.setColor(supportbot.EmbedColour)
.setFooter(supportbot.EmbedFooter, message.author.displayAvatarURL());
if (message.member.roles.cache.some(role => role.name === supportbot.Staff || supportbot.Admin)) {
HelpCommandEmbed.addFields(
{ name: '🔐 Staff Commands', value: `${staffCommands}\n`, inline: false },
)
}
message.channel.send({ embed: HelpCommandEmbed });
}
};
-36
View File
@@ -1,36 +0,0 @@
// SupportBot, Created by Emerald Services
// Links Command
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const { execute } = require("./help");
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.LinksCommand,
description: supportbot.LinksDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.LinksCommand}!`);
const LinksEmbed = new Discord.MessageEmbed()
.setColor(supportbot.EmbedColour)
let botLinks = supportbot.LINKS;
let links = '';
for ( let name in botLinks ) {
links += `[${name}](${botLinks[ name ]})\n`;
};
LinksEmbed.addField(supportbot.LinksTitle, links)
message.channel.send({ embed: LinksEmbed });
}
};
-272
View File
@@ -1,272 +0,0 @@
// SupportBot, Created by Emerald Services
// Ticket Command
const Discord = require("discord.js");
const bot = new Discord.Client()
const fs = require("fs")
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
const TicketNumberID = require('../utils/TicketNumber.js');
const reacted = [];
module.exports = {
name: supportbot.NewTicket,
description: supportbot.NewTicketDesc,
execute(message, args) {
if (!message.channel.name === supportbot.ReactionChannel) {
if (supportbot.DeleteMessages == "true") message.delete();
}
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.NewTicket}!`);
// Ticket ID
let ticketNumberID = TicketNumberID.pad(message.guild.id);
// Ticket Subject
const TicketSubject = args || supportbot.NoTicketSubject;
// Ticket Exists
const TicketExists = new Discord.MessageEmbed()
.setTitle("Ticket Exists!")
.setDescription(`${supportbot.TicketExists}`)
.setColor(supportbot.WarningColour)
if (message.guild.channels.cache.find(SupportTicket => SupportTicket.name === `${supportbot.TicketChannel}-${ticketNumberID}`))
return message.channel.send({ embed: TicketExists });
message.guild.channels.create(`${supportbot.TicketChannel}-${ticketNumberID}`, {
type: "text",
}).then(SupportTicket => {
let AllUsers = message.guild.roles.cache.find(everyone => everyone.name === '@everyone')
let SupportStaff = message.guild.roles.cache.find(SupportTeam => SupportTeam.name === supportbot.Staff)
let Admins = message.guild.roles.cache.find(AdminUser => AdminUser.name === supportbot.Admin)
let DeptRole1 = message.guild.roles.cache.find(DepartmentRole => DepartmentRole.name === `${supportbot.DepartmentRole_1}`)
let DeptRole2 = message.guild.roles.cache.find(DepartmentRole => DepartmentRole.name === `${supportbot.DepartmentRole_2}`)
let DeptRole3 = message.guild.roles.cache.find(DepartmentRole => DepartmentRole.name === `${supportbot.DepartmentRole_3}`)
SupportTicket.updateOverwrite(AllUsers, {
VIEW_CHANNEL: false,
READ_MESSAGES: false,
SEND_MESSAGES: false,
})
SupportTicket.updateOverwrite(message.author, {
VIEW_CHANNEL: true,
READ_MESSAGES: true,
SEND_MESSAGES: true,
})
SupportTicket.updateOverwrite(SupportStaff, {
VIEW_CHANNEL: true,
READ_MESSAGES: true,
SEND_MESSAGES: true,
})
SupportTicket.updateOverwrite(Admins, {
VIEW_CHANNEL: true,
READ_MESSAGES: true,
SEND_MESSAGES: true,
})
// Ticket Category
let TicketCategory = message.guild.channels.cache.find(category => category.name === supportbot.TicketCategory)
if (TicketCategory) {
SupportTicket.setParent(TicketCategory.id)
} else {
if (message.guild.channels.cache.get(supportbot.TicketCategory)) {
SupportTicket.setParent(message.guild.channels.cache.get(supportbot.TicketCategory).id);
}
}
// Ticket Created, Message Sent
if (supportbot.AllowTicketMentions === "true") {
SupportTicket.send(`<@${message.author.id}>`)
}
const TicketMessage = new Discord.MessageEmbed()
.setTitle(supportbot.Ticket_Title.replace(/%ticketauthor%/g, message.author.id).replace(/%ticketid%/g, SupportTicket.id).replace(/%ticketusername%/g, message.author.username))
.setDescription(supportbot.TicketMessage.replace(/%ticketauthor%/g, message.author.id).replace(/%ticketid%/g, SupportTicket.id).replace(/%ticketusername%/g, message.author.username))
.setColor(supportbot.EmbedColour)
if (supportbot.TicketSubject === "embed") {
if (TicketSubject != 'No Reason Provided.') {
TicketMessage.addFields({ name: 'Reason', value: TicketSubject })
}
}
if (supportbot.TicketSubject === "description") {
if (TicketSubject != 'No Reason Provided.') {
SupportTicket.setTopic(`Reason: ${TicketSubject} - User ID: ${message.author.id} - Ticket: ${SupportTicket.name}`)
}
}
if (supportbot.TicketDepartments === "true") {
TicketMessage.addFields({ name: 'Departments', value: `${supportbot.DepartmentEmoji_1} **${supportbot.DepartmentTitle_1}**\n${supportbot.DepartmentEmoji_2} **${supportbot.DepartmentTitle_2}**\n${supportbot.DepartmentEmoji_3} **${supportbot.DepartmentTitle_3}**` })
}
SupportTicket.send({ embed: TicketMessage }).then( async function(msg) {
const Emoji_1 = supportbot.DepartmentEmoji_1;
const Emoji_2 = supportbot.DepartmentEmoji_2;
const Emoji_3 = supportbot.DepartmentEmoji_3;
reacted[ticketNumberID] = false;
if (supportbot.TicketDepartments === "true") {
await msg.react(Emoji_1);
await msg.react(Emoji_2);
await msg.react(Emoji_3);
let filter = (reaction, user) => {
if (user.id !== message.author.id) return;
if (typeof reacted[ticketNumberID] !== "boolean") return;
delete reacted[ticketNumberID];
if (reaction.emoji.name === Emoji_1) {
SupportTicket.updateOverwrite(message.author.id, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
SupportTicket.updateOverwrite(Admins, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
SupportTicket.updateOverwrite(DeptRole1, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
if (supportbot.AllowStaff === "true") {
SupportTicket.updateOverwrite(SupportStaff, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
}
if (supportbot.AllowStaff === "false") {
SupportTicket.updateOverwrite(SupportStaff, { VIEW_CHANNEL: false, READ_MESSAGES: true, SEND_MESSAGES: true, })
}
const Department1 = new Discord.MessageEmbed()
.setTitle(`> Thank for reaching out to the **${supportbot.DepartmentTitle_1} Department**. Please provide us information regarding your query.`)
.setColor(supportbot.EmbedColour)
SupportTicket.send({ embed: Department1 });
if (supportbot.AllowTicketMentions === "true") {
SupportTicket.send(`@here`)
}
}
if (reaction.emoji.name === Emoji_2) {
SupportTicket.updateOverwrite(message.author.id, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
SupportTicket.updateOverwrite(Admins, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
SupportTicket.updateOverwrite(DeptRole2, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
if (supportbot.AllowStaff === "true") {
SupportTicket.updateOverwrite(SupportStaff, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
}
if (supportbot.AllowStaff === "false") {
SupportTicket.updateOverwrite(SupportStaff, { VIEW_CHANNEL: false, READ_MESSAGES: true, SEND_MESSAGES: true, })
}
const Department2 = new Discord.MessageEmbed()
.setTitle(`> Thank for reaching out to the **${supportbot.DepartmentTitle_2} Department**. Please provide us information regarding your query.`)
.setColor(supportbot.EmbedColour)
SupportTicket.send({ embed: Department2 });
if (supportbot.AllowTicketMentions === "true") {
SupportTicket.send(`@here`)
}
}
if (reaction.emoji.name === `${Emoji_3}`) {
SupportTicket.updateOverwrite(message.author.id, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
SupportTicket.updateOverwrite(Admins, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
SupportTicket.updateOverwrite(DeptRole3, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
SupportTicket.updateOverwrite(SupportStaff, { VIEW_CHANNEL: false, READ_MESSAGES: true, SEND_MESSAGES: true, })
if (supportbot.AllowStaff === "true") {
SupportTicket.updateOverwrite(SupportStaff, { VIEW_CHANNEL: true, READ_MESSAGES: true, SEND_MESSAGES: true, })
}
if (supportbot.AllowStaff === "false") {
SupportTicket.updateOverwrite(SupportStaff, { VIEW_CHANNEL: false, READ_MESSAGES: true, SEND_MESSAGES: true, })
}
const Department3 = new Discord.MessageEmbed()
.setTitle(`> Thank for reaching out to the **${supportbot.DepartmentTitle_3} Department**. Please provide us information regarding your query.`)
.setColor(supportbot.EmbedColour)
SupportTicket.send({ embed: Department3 });
if (supportbot.AllowTicketMentions === "true") {
SupportTicket.send(`@here`)
}
}
return [Emoji_1, Emoji_2, Emoji_3].includes(reaction.emoji.name) && user.id !== message.author.id;
}
msg.awaitReactions(filter, {
max: 4,
time: 60000,
errors: ['time']
}).then(async collected => {
});
setTimeout(async function() {
if (typeof reacted[ticketNumberID] == "boolean") {
delete reacted[ticketNumberID];
//delete channel because didn't react in a minute
}
}, 60000);
}
});
if (message.channel.name === supportbot.ReactionChannel) {
const CreatedTicket = new Discord.MessageEmbed()
.setDescription(supportbot.TicketCreatedAlert.replace(/%ticketauthor%/g, message.author.id).replace(/%ticketid%/g, SupportTicket.id).replace(/%ticketusername%/g, message.author.username))
.setColor(supportbot.EmbedColour)
message.channel.send({embed: CreatedTicket}).then((r) => {
r.delete({ timeout:5000 })
})
} else {
const CreatedTicket = new Discord.MessageEmbed()
.setDescription(supportbot.TicketCreatedAlert.replace(/%ticketauthor%/g, message.author.id).replace(/%ticketid%/g, SupportTicket.id).replace(/%ticketusername%/g, message.author.username))
.setColor(supportbot.EmbedColour)
message.channel.send({embed: CreatedTicket});
}
fs.writeFileSync("./storage/SupportTickets.json", '{\n "ticket": "' + SupportTicket.name + '", \n "id":' + message.author.id + "\n}", (err) => {
if (!err) return;
console.error(err)
})
// Ticket Logs
const errornochannel = new Discord.MessageEmbed()
.setTitle("SupportBot Error!")
.setDescription(`:x: **Error!** Channel not Found, This command cannot be executed proberbly as their is no channel within this server.\nThis is configurable via **supportbot-config.yml**\n\nChannel Required: \`${supportbot.TicketLog}\`\n\nError Code: \`SB-03\``)
.setColor(supportbot.ErrorColour);
const TicketLogs = new Discord.MessageEmbed()
.setTitle("Ticket Log")
.setThumbnail(supportbot.Ticket_Thumbnail)
.addFields(
{ name: 'Ticket', value: `<#${SupportTicket.id}>` },
{ name: 'User', value: `<@${message.author.id}>` },
)
.setColor(supportbot.EmbedColour)
.setFooter(supportbot.EmbedFooter)
let locateChannel = message.guild.channels.cache.find(LocateChannel => LocateChannel.name === supportbot.TicketLog)
if(!locateChannel) return message.channel.send({ embed: errornochannel });
locateChannel.send({ embed: TicketLogs });
})
}
};
-27
View File
@@ -1,27 +0,0 @@
// SupportBot, Created by Emerald Services
// Ping Command
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.PingCommand,
description: supportbot.PingDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.PingCommand}!`)
let ping = Date.now() - message.createdTimestamp + " ms";
const PingCommandEmbed = new Discord.MessageEmbed()
.setDescription(`🏓 **Pong!** \`${Date.now() - message.createdTimestamp}ms\``)
.setColor(supportbot.EmbedColour)
message.channel.send({ embed: PingCommandEmbed });
}
};
-64
View File
@@ -1,64 +0,0 @@
// SupportBot, Created by Emerald Services
// Remove User
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.RemoveUser,
description: supportbot.RemoveUserDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.RemoveUser}!`);
let SupportStaff = message.guild.roles.cache.find(SupportTeam => SupportTeam.name === supportbot.Staff)
let Admins = message.guild.roles.cache.find(AdminUser => AdminUser.name === supportbot.Admin)
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(`${supportbot.IncorrectPerms}\n\nRole Required: \`${supportbot.Staff}\` or \`${supportbot.Admin}\``)
.setColor(supportbot.WarningColour)
if (message.member.roles.cache.has(SupportStaff.id) || message.member.roles.cache.has(Admins.id)) {
if (!message.channel.name.startsWith( `${supportbot.TicketChannel}-` )) {
const Exists = new Discord.MessageEmbed()
.setTitle("No Ticket Found!")
.setDescription(`${supportbot.NoValidTicket}`)
.setColor(supportbot.WarningColour);
message.channel.send({ embed: Exists });
return;
}
let rUser = message.guild.member(message.mentions.users.first() || message.guild.members.cache.get(args[0]));
const UserNotExist = new Discord.MessageEmbed()
.setTitle("User Not Found!")
.setDescription(`${supportbot.UserNotFound}\n\nTry Again:\`${supportbot.Prefix}${supportbot.RemoveUser} <user#0000>\``)
.setColor(supportbot.ErrorColour)
if (!rUser) return message.channel.send({ embed: UserNotExist });
message.channel.updateOverwrite(rUser, {
VIEW_CHANNEL: false,
CREATE_INVITE: false,
SEND_MESSAGES: false,
READ_MESSAGES: false
});
const Complete = new Discord.MessageEmbed()
.setTitle("User Removed!")
.setDescription(supportbot.RemovedUser.replace(/%user%/g, rUser.id))
.setTimestamp()
.setColor(supportbot.EmbedColour)
message.channel.send({ embed: Complete });
} else {
return message.channel.send({ embed: NoPerms });
}
}
};
-62
View File
@@ -1,62 +0,0 @@
// SupportBot, Created by Emerald Services
// Suggest Command
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = {
name: supportbot.SuggestCommand,
description: supportbot.SuggestionDesc,
execute(message, args) {
if (supportbot.DeleteMessages == "true") message.delete();
let locateChannel = message.guild.channels.cache.find(SuggestionChannel => SuggestionChannel.name === supportbot.SuggestionChannel);
console.log(`\u001b[32m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `${message.author.tag} has executed ${supportbot.Prefix}${supportbot.SuggestCommand}!`);
const errornochannel = new Discord.MessageEmbed()
.setTitle("Invalid Channel")
.setDescription(`${supportbot.InvalidChannel}\n\nChannel Required: \`${supportbot.SuggestionChannel}\``)
.setColor(supportbot.ErrorColour);
if(!locateChannel) return message.channel.send({ embed: errornochannel });
const embed = new Discord.MessageEmbed()
.setDescription(`> **${supportbot.SuggestionStarter}**`)
.setColor(supportbot.EmbedColour)
message.channel.send({ embed: embed });
let suggestion = []
message.channel.awaitMessages(response => response.content.length > 2, {
max: 1,
time: 500000,
errors: ['time'],
}).then((collected) => {
suggestion.push(collected.map(r => r.content));
const SuggestionMessage = new Discord.MessageEmbed()
.setColor(supportbot.EmbedColour)
.setFooter(supportbot.EmbedFooter)
.setTitle(supportbot.SuggestionTitle)
.setDescription(`\`\`\`${suggestion}\`\`\``)
.addFields( { name: "From", value: `<@${message.author.id}>`, inline: false }, )
locateChannel.send({ embed: SuggestionMessage }).then(async function(msg) {
msg.react(supportbot.SuggestReact_1).then(() => msg.react(supportbot.SuggestReact_2));
});
const SuggestionComplete = new Discord.MessageEmbed()
.setColor(supportbot.SuccessColour)
.setDescription(`:white_check_mark: Your suggestion has been successfully created. <#${locateChannel.id}>`)
message.channel.send({ embed: SuggestionComplete })
});
}
};
-49
View File
@@ -1,49 +0,0 @@
// SupportBot 6.0, Created by Emerald Services
// Ready Event
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = async (bot, member) => {
if (supportbot.SystemMessages === "true") {
const SystemChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.SystemMessage_Channel)
if (!SystemChannel) return;
console.log(`[${supportbot.Bot_Name}]: ${member.user.username} has joined ${member.guild.name}!`)
console.log(supportbot.AutoRole_Role)
if (supportbot.SystemMessage_Type === "embed") {
const GuildAddMember = new Discord.MessageEmbed()
.setTitle(supportbot.Welcome_Title)
.setDescription(supportbot.WelcomeMessage.replace(/%member%/g, member.user.username).replace(/%guildname%/g, member.guild.name))
.setColor(supportbot.EmbedColour)
if (supportbot.SystemMessage_Icon === "BOT") {
GuildAddMember.setThumbnail(bot.user.displayAvatarURL())
}
if (supportbot.SystemMessage_Icon === "USER") {
GuildAddMember.setThumbnail(member.user.displayAvatarURL())
}
if (supportbot.SystemMessage_EmbedFooter === "true") {
GuildAddMember.setFooter(supportbot.EmbedFooter)
}
SystemChannel.send({ embed: GuildAddMember });
}
if (supportbot.SystemMessage_Type === "normal") {
SystemChannel.send(supportbot.WelcomeMessage.replace(/%member%/g, member.user.username).replace(/%guildname%/g, member.guild.name))
}
}
};
-48
View File
@@ -1,48 +0,0 @@
// SupportBot 6.0, Created by Emerald Services
// Ready Event
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = async (bot, member) => {
if (supportbot.SystemMessages === "true") {
const SystemChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.SystemMessage_Channel)
if (!SystemChannel) return;
console.log(`[${supportbot.Bot_Name}]: ${member.user.username} has left ${member.guild.name}!`)
if (supportbot.SystemMessage_Type === "embed") {
const GuildRemoveMember = new Discord.MessageEmbed()
.setTitle(supportbot.Leave_Title)
.setDescription(supportbot.LeaveMessage.replace(/%member%/g, member.user.username).replace(/%guildname%/g, member.guild.name))
.setColor(supportbot.EmbedColour)
if (supportbot.SystemMessage_Icon === "BOT") {
GuildRemoveMember.setThumbnail(bot.user.displayAvatarURL())
}
if (supportbot.SystemMessage_Icon === "USER") {
GuildRemoveMember.setThumbnail(member.user.displayAvatarURL())
}
if (supportbot.SystemMessage_EmbedFooter === "true") {
GuildRemoveMember.setFooter(supportbot.EmbedFooter)
}
SystemChannel.send({ embed: GuildRemoveMember });
}
if (supportbot.SystemMessage_Type === "normal") {
SystemChannel.send(supportbot.LeaveMessage.replace(/%member%/g, member.user.username).replace(/%guildname%/g, member.guild.name))
}
}
};
-22
View File
@@ -1,22 +0,0 @@
// SupportBot 6.0, Created by Emerald Services
// Message Event
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
module.exports = async (bot, message) => {
if(message.author.bot) return;
if(message.channel.type === "dm") return;
if (message.content.indexOf(supportbot.Prefix) !== 0) return;
let messageArray = message.content.split(" ");
const args = message.content.slice(supportbot.Prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
const cmd = bot.commands.get(command);
if(!cmd) return;
cmd.execute(message, args);
};
-36
View File
@@ -1,36 +0,0 @@
// SupportBot 6.0, Created by Emerald Services
// Message Reaction Event
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
const tickets = yaml.load(fs.readFileSync('./storage/ticketreaction.yml', 'utf8'));
module.exports = async (client, reaction, user) => {
let message = {
guild: reaction.message.channel.guild,
author: user,
content: "Not available",
channel: reaction.message.channel
}
if (supportbot.ReactionTickets === "true") {
if (reaction.message.id === tickets.ReactionMessage_ID) {
if (reaction.emoji.name == supportbot.ReactionEmoji || reaction.emoji.id == supportbot.ReactionEmoji) {
await reaction.users.remove(user.id)
try {
const cmd = client.commands.get("ticket");
if(!cmd) return;
cmd.execute(message, "undefined");
} catch (error) {
console.error(error);
}
}
}
}
};
-54
View File
@@ -1,54 +0,0 @@
// SupportBot 6.0, Created by Emerald Services
// Ready Event
const Discord = require("discord.js");
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
const tickets = yaml.load(fs.readFileSync('./storage/ticketreaction.yml', 'utf8'));
module.exports = async (bot) => {
bot.user.setActivity(supportbot.BotActivity, {
type: supportbot.ActivityType,
url: supportbot.StreamingURL
});
console.log(`\u001b[32m`, `―――――――――――――――――― SupportBot ――――――――――――――――――`)
console.log(`\u001b[37m`, `${supportbot.Bot_Name} has successfully connected to discord`)
console.log(`\u001b[32m`, `―――――――――――――――――― SupportBot ――――――――――――――――――`)
if (supportbot.ReactionTickets === "true") {
let chan1 = bot.channels.cache.find(channel => channel.name === supportbot.ReactionChannel)
if (!chan1) {
console.log('\u001b[33m', "[WARN] Ticket reaction panel is not setup, You can do so via the configuration file!")
return false;
}
chan1.messages.fetch(tickets.ReactionMessage_ID).catch(r => {
let embed = new Discord.MessageEmbed()
.setTitle(supportbot.ReactionMessage.replace(/%reaction_emoji%/g, supportbot.ReactionEmoji))
.setColor(supportbot.SuccessColour)
.setFooter(supportbot.EmbedFooter);
bot.channels.cache.find(channel => channel.name === supportbot.ReactionChannel).send({
embed: embed
}).then(r => {
let data = {
"ReactionMessage_ID": `${r.id}`
}
let yamlStr = yaml.dump(data);
fs.writeFileSync('./storage/ticketreaction.yml', yamlStr, 'utf8');
r.react(supportbot.ReactionEmoji);
}).catch(e => {
console.log(e)
})
})
}
};
Executable → Regular
+33 -81
View File
@@ -1,92 +1,44 @@
// _________ __ __________ __
// / _____/__ ________ ______ ____________/ |\______ \ _____/ |_
// \_____ \| | \____ \\____ \ / _ \_ __ \ __\ | _// _ \ __\
// / \ | / |_> > |_> > <_> ) | \/| | | | ( <_> ) |
// /_______ /____/| __/| __/ \____/|__| |__| |______ /\____/|__|
// \/ |__| |__| \/
// ___ _ ___ _
// / __> _ _ ___ ___ ___ _ _ _| |_ | . > ___ _| |_
// \__ \| | || . \| . \/ . \| '_> | | | . \/ . \ | |
// <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_|
// |_| |_|
//
// SupportBot version 6.1
// Created by Emerald Services
// Installed with MIT License
// SupportBot created by Emerald Services
// Installed with MIT License
//
// Support Server: discord.gg/jspKFcE
// Discord Support: https://emeraldsrv.dev/discord
// Community Resources: https://emeraldsrv.dev/resources
const Discord = require("discord.js");
const fs = require("fs");
const bot = new Discord.Client();
bot.commands = new Discord.Collection();
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
const { promisify } = require("util");
const readdir = promisify(require("fs").readdir);
String.prototype.toProperCase = function () {
return this.replace(
/([^\W_]+[^\s-]*) */g,
(txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
);
};
const init = async () => {
const evtFiles = await readdir("./events/");
evtFiles.forEach((file, i) => {
const eventName = file.split(".")[0];
const event = require(`./events/${file}`);
console.info(`\u001b[37m`, `[${supportbot.Bot_Name}]:`, `\u001b[31m`, `#${i + 1} Event Loaded: ${eventName.toProperCase()} `);
bot.on(eventName, event.bind(null, bot));
delete require.cache[require.resolve(`./events/${file}`)];
});
console.info(`\u001b[37m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `Successfully loaded ${evtFiles.length} events.`);
console.info(`\u001b[37m`, "-----------------------------------------------------------------------------");
};
init();
fs.readdir("./commands/", (err, files) => {
if (err) console.info(err, "error");
let jsfiles = files.filter((f) => f.split(".").pop() === "js");
if (jsfiles.length <= 0) {
console.log(`[${supportbot.Bot_Name}]: No commands found. Try to Re-download the resource`);
return;
}
jsfiles.forEach((f, i) => {
let props = require(`./commands/${f}`);
console.info(`\u001b[37m`, `[${supportbot.Bot_Name}]:`, `\u001b[31m`, `#${i + 1} Command Loaded: ${props.name.toProperCase()}`);
bot.commands.set(props.name, props);
});
console.info(`\u001b[37m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `Loaded ${jsfiles.length} commands!`);
console.info(`\u001b[37m`, "-----------------------------------------------------------------------------");
const Client = require("./Structures/Client.js");
const client = new Client({
intents: ['Guilds', 'GuildMembers', 'GuildMessages']
});
fs.readdir("./addons/", (err, files) => {
if (err) console.info(err, "error");
let jsfiles = files.filter((f) => f.split(".").pop() === "js");
client.start(supportbot.General.Token);
if (jsfiles.length <= 0) {
console.log(`[${supportbot.Bot_Name}]: No addons found. You can download addons from https://emeraldservices.xyz`);
return;
}
jsfiles.forEach((f, i) => {
let props = require(`./addons/${f}`);
console.info(`\u001b[37m`, `[${supportbot.Bot_Name}]:`, `\u001b[31m`, `#${i + 1} Command Loaded: ${props.name.toProperCase()}`);
bot.commands.set(props.name, props);
});
console.info(`\u001b[37m`, `[${supportbot.Bot_Name}]:`, `\u001b[32m`, `Loaded ${jsfiles.length} commands!`);
console.info(`\u001b[37m`, "-----------------------------------------------------------------------------");
});
bot.login(supportbot.Token);
Generated Executable → Regular
+1521 -705
View File
File diff suppressed because it is too large. Load diff
Executable → Regular
+16 -14
View File
@@ -1,27 +1,29 @@
{
"name": "supportbot",
"version": "6.1",
"description": "SupportBot | #1 Self-Hosted Ticket Bot",
"version": "8.0.1",
"description": "SupportBot is an open-sourced support system for discord. It's completely free to use with high amounts of customization to match your own brand.",
"main": "index.js",
"dependencies": {
"discord.js": "^12.5.1",
"javascript-obfuscator": "^2.9.4",
"js-yaml": "^3.14.0"
},
"devDependencies": {
"node-fetch": ">=2.6.1"
},
"scripts": {
"test": "help"
"setup": "npm i && node index.js",
"start": "node index.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/1tzemerald/SupportBot.git"
"url": "git+https://github.com/Emerald-Services/SupportBot.git"
},
"author": "Emerald Services",
"license": "MIT",
"bugs": {
"url": "https://github.com/1tzemerald/SupportBot/issues"
"url": "https://github.com/Emerald-Services/SupportBot/issues"
},
"homepage": "https://emeraldsrv.dev"
"homepage": "https://github.com/Emerald-Services/SupportBot#readme",
"dependencies": {
"@vitalets/google-translate-api": "^8.0.0",
"axios": "^1.7.2",
"chatgpt": "^5.2.5",
"discord.js": "^14.13.0",
"js-yaml": "^4.1.0",
"moment": "^2.29.3",
"openai": "^4.50.0"
}
}
-4
View File
@@ -1,4 +0,0 @@
{
"ticket": "ticket-0012",
"id":419821884431925260
}
-8
View File
@@ -1,8 +0,0 @@
{
"716992597377286145": {
"id": 65
},
"805909541979029524": {
"id": 13
}
}
-1
View File
@@ -1 +0,0 @@
ReactionMessage_ID: ''
-195
View File
@@ -1,195 +0,0 @@
# _________ __ __________ __
# / _____/__ ________ ______ ____________/ |\______ \ _____/ |_
# \_____ \| | \____ \\____ \ / _ \_ __ \ __\ | _// _ \ __\
# / \ | / |_> > |_> > <_> ) | \/| | | | ( <_> ) |
# /_______ /____/| __/| __/ \____/|__| |__| |______ /\____/|__|
# \/ |__| |__| \/
#
# SupportBot version 6.1
# Created by Emerald Services
# Installed with MIT License
#
# Support Server: discord.gg/jspKFcE
# General Bot Configuration
Token: "BOT_TOKEN_HERE"
Prefix: "-"
Bot_Name: "SupportBot"
BotActivity: "-help | SupportBot"
StreamingURL: "https://www.twitch.tv/YOUR_TWITCH_NAME"
# Must set ActivityType to STREAMING in order for Streaming URL to work in the bots status.
ActivityType: "PLAYING"
# Activity status can either be PLAYING, WATCHING, LISTENING or STREAMING.
DeleteMessages: "true"
# Embed Configuration
EmbedColour: "#04b545"
EmbedFooter: "SupportBot | The #1 Supportive Discord Bot"
ErrorColour: "#d12519"
SuccessColour: "#04b545"
WarningColour: "#fca117"
# Role Configuration
AutoRole: "true"
# By setting "AutoRole to 'true' the bot will automatically apply the role below when members joins. Set to 'false' to disable this feature.
AutoRole_Role: "Member"
LockdownRole: "@everyone"
Staff: "Staff"
Admin: "Admin"
# Ticket Configuration
TicketChannel: "ticket"
TicketCategory: "Tickets"
TicketLog: "ticket-logs"
TranscriptLog: "transcripts"
TicketSubject: "description"
# TicketSubject: "description" means that the subject (reason) of the ticket will be displayed upon the channel description if set to "embed" it will be displayed within the embed.
AllowTicketMentions: "true"
# Set to "true" to allow the ticket to mention the author and the support team.
# Set to "false" to dis-allow mentions within tickets.
# Ticket Panel (Ticket Reaction Create)
ReactionTickets: "true"
ReactionMessage: "React with %reaction_emoji% to create a Support Ticket!"
ReactionChannel: "create-ticket"
ReactionEmoji: "📩"
# Custom Emojis: <:test:EMOJI_ID>
Ticket_Thumbnail: "https://images.emojiterra.com/google/android-pie/512px/1f39f.png"
Ticket_Title: "Server Support | %ticketusername%"
TicketMessage: "Hello <@%ticketauthor%>, Thank you for creating a support ticket\nPlease wait patiently whilst a member of our team reaches out to you."
NoTicketSubject: "No Reason Provided!"
TicketCreatedAlert: ":ticket: Your support ticket has been created: <#%ticketid%>"
TranscriptTitle: "Ticket Transcript"
AddedUser: "👍 <@%user%> has been added to this ticket"
RemovedUser: "👍 <@%user%> has been removed from this ticket"
ClosingTicket: ":warning: You have requested to close your support ticket."
ClosingConfirmation_Word: "confirm"
CloseConfirmation: "true"
# CloseConfirmation to true will make users confirm that they want to close a their ticket, settings to false will just close the ticket.
# Ticket Department Configuration
TicketDepartments: "true"
# This option enable or disable the ticket departments. If set false Ticket Departments will not work
AllowStaff: "true"
# AllowStaff is an option to whether or not you want the users with the "Staff" role to be able to view inside tickets. If set false "Staff" will not view tickets.
DepartmentEmoji_1: "🙋"
DepartmentEmoji_2: "💸"
DepartmentEmoji_3: "📗"
# Ticket emojis, the emojis are what users will need to react with inorder to proceed furthur if departments are enabled.
DepartmentTitle_1: "Support"
DepartmentTitle_2: "Billing"
DepartmentTitle_3: "Other"
# Ticket department title, This is the title for a ticket department to help users know what is available.
DepartmentRole_1: "Support"
DepartmentRole_2: "Admin"
DepartmentRole_3: "Support"
# Ticket roles are the roles that will be able to gain access to tickets depending on what department has been choosen.
# System Message Configuration
SystemMessages: "true"
SystemMessage_Channel: "system-messages"
SystemMessage_Type: "embed"
# There are 2 types of how you can send system messages, 'normal' or 'embed'
SystemMessage_Icon: "USER"
Welcome_Title: "User Joined!"
WelcomeMessage: "Hello %member%, Welcome to %guildname%!"
# %member% define the user who joined and %guildnamne% defines the server name.
Leave_Title: "User Left!"
LeaveMessage: "Goodbye %member%, Thank you for visting %guildname%!"
# %member% define the user who left and %guildnamne% defines the server name.
SystemMessage_EmbedFooter: "false"
# LINKS Configuration
LinksTitle: "Quick Links"
LINKS:
"Website": "https://www.example.com"
"Store": "https://store.example.com"
"Discord": "https://discord.gg/example"
# "Twitter": "https://twitter.com/example"
# Suggestions Configuration
SuggestionChannel: "suggestions"
SuggestionTitle: "Suggestion"
SuggestionStarter: "What would you like to suggest?"
SuggestReact_1: 👍
SuggestReact_2: 👎
# Announcement Configuration
AnnouncementChannel: "announcements"
AnnouncementTitle: "Servername Announcement"
AnnouncementIcon: "https://i.imgur.com/HbkZyB7.png"
AnnouncementStarter: "What would you like to announce?"
# General Command Configuration
HelpCommand: "help"
LinksCommand: "links"
PingCommand: "ping"
SuggestCommand: "suggest"
# Support Command Configuration
NewTicket: "ticket"
CloseTicket: "close"
AddUser: "add"
RemoveUser: "remove"
RenameTicket: "rename"
# Staff Command Configuration
BotSay: "say"
# Admin Command Configuration
AnnounceCommand: "announce"
# Commmand Descriptions
NewTicketDesc: "Create a new support ticket"
AnnounceDesc: "Create a server announcement"
CloseTicketDesc: "Close your support ticket"
LinksDesc: "View some important links"
PingDesc: "Get the bot's latency"
HelpDesc: "Get a list of all the commands"
RemoveUserDesc: "Remove a user from a support ticket"
AddUserDesc: "Add a user to a support ticket"
SuggestionDesc: "Create a server suggestion"
BotSayDesc: "Say something with the bot"
# Error / Warining Messages
IncorrectPerms: ":x: **Err!** You do not have the correct permissions to use this command."
InvalidChannel: ":x: **Err!** Channel not found. Please create it!"
UserNotFound: ":x: **Err!** This user doesn't exist, Are they in this server?"
NoValidTicket: ":warning: You cannot execute this command here. This command is used when closing a ticket."
TicketExists: ":warning: This ticket cannot be opened, It already exists!"
-72
View File
@@ -1,72 +0,0 @@
// SupportBot Utils
// Ticket Numbers
const discord = require("discord.js")
const fs = require("fs");
const yaml = require('js-yaml');
const supportbot = yaml.load(fs.readFileSync('./supportbot-config.yml', 'utf8'));
class TicketNumberID {
static pad(guildId) {
let n = this.get(guildId) + '';
let z = '0';
let width = 4;
setTimeout(() => {
this.set(guildId, this.get(guildId) + 1);
}, 50);
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
static get(guildId) {
let ticketnumberID = JSON.parse(fs.readFileSync("./storage/TicketID.json", "utf8"));
if (!ticketnumberID[guildId]) {
ticketnumberID[guildId] = {
id: 0
}
fs.writeFileSync("./storage/TicketID.json", JSON.stringify(ticketnumberID, null, 4), err => {
if (err) console.log(err);
});
return 0;
} else {
return ticketnumberID[guildId].id;
}
}
static set(guildId, value) {
let ticketnumberID = JSON.parse(fs.readFileSync("./storage/TicketID.json", "utf8"));
ticketnumberID[guildId] = {
id: value
}
fs.writeFileSync("./storage/TicketID.json", JSON.stringify(ticketnumberID, null, 4), err => {
if (err) console.log(err);
});
return value;
}
static reset(guildId) {
let ticketnumberID = JSON.parse(fs.readFileSync("./storage/TicketID.json", "utf8"));
ticketnumberID[guildId] = {
id: 0
}
fs.writeFileSync("./storage/TicketID.json", JSON.stringify(ticketnumberID, null, 4), err => {
if (err) console.log(err);
});
return 0;
}
}
module.exports = TicketNumberID;