Open Ticket v4.2: Config Update (JSONC)

This commit is contained in:
DJj123dj
2026-05-17 22:28:23 +02:00
parent afd7f80b8d
commit dd8d5a12d6
106 changed files with 2199 additions and 1198 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
# Contributing Guidelines # Contributing Guidelines
<img src="https://apis.dj-dj.be/cdn/openticket/logo.png" alt="Open Ticket Logo" width="500px"> <img src="https://apis.dj-dj.be/cdn/openticket/logo.png" alt="Open Ticket Logo" width="500px">
[![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-4.1.3-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.1.3) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj) [![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-4.2.0-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.2.0) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj)
These are the Contributing Guidelines of Open Ticket!<br> These are the Contributing Guidelines of Open Ticket!<br>
Here you can find everything you need to know about contributing to Open Ticket.<br> Here you can find everything you need to know about contributing to Open Ticket.<br>
+8 -11
View File
@@ -19,18 +19,15 @@ This list will be updated on every release.
| Version | Supported | Notes | | Version | Supported | Notes |
|------------|-----------|---------------------------------------------------------------| |------------|-----------|---------------------------------------------------------------|
| 4.2.0 | 🟦 | In Development | | 4.2.x | 🟦 | In Development |
| 4.1.x | 🟦 | In Development | | 4.2.1 | 🟦 | In Development |
| 4.1.3 | ✅ | | | 4.2.0 | ✅ | |
| 4.1.2 | ✅ | | | 4.1.3 | ✅ | (LTS) Long-Term-Support, Until September 2026 |
| 4.1.1 | ✅ | Supported Until April 2026 (LTS) | | 4.1.2 | 🚧 | |
| 4.1.1 | 🚧 | |
| 4.1.0 | 🚧 | | | 4.1.0 | 🚧 | |
| 4.0.7 | 🚧 | | | 4.0.7 | 🟧 | Deprecated |
| 4.0.6 | 🚧 | | | < 4.0.7 | ❌ | |
| 4.0.5 | 🟧 | Deprecated |
| 4.0.4 | 🟧 | Deprecated |
| < 4.0.4 | 🟧 | Deprecated, Transcripts v2.0, Documentation Only |
| < 4.0.0 | ❌ | |
### 🕷️ Reporting Vulnerabilities ### 🕷️ Reporting Vulnerabilities
You can report vulnerabilities, errors & bugs using one of the following methods: You can report vulnerabilities, errors & bugs using one of the following methods:
+4 -1
View File
@@ -2,7 +2,7 @@
<img src="https://apis.dj-dj.be/cdn/openticket/logo.png" alt="Open Ticket Logo" width="500px"> <img src="https://apis.dj-dj.be/cdn/openticket/logo.png" alt="Open Ticket Logo" width="500px">
[![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3)
[![version](https://img.shields.io/badge/version-4.1.3-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.1.3) [![version](https://img.shields.io/badge/version-4.2.0-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.2.0)
[![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj)
[![Open Ticket supports Pterodactyl Eggs!](https://img.shields.io/badge/pterodactyl-supported-10539F?style=flat-square&logo=pterodactyl)](.eggs/README.md) [![Open Ticket supports Pterodactyl Eggs!](https://img.shields.io/badge/pterodactyl-supported-10539F?style=flat-square&logo=pterodactyl)](.eggs/README.md)
@@ -20,6 +20,9 @@ It's recommended to provide at least `1GB` of **Memory/RAM** and `5GB` of **disk
[**`openticket-egg-main.json` (Recommended)**](openticket-egg-main.json) [**`openticket-egg-main.json` (Recommended)**](openticket-egg-main.json)
- This egg will use the `main` branch of Open Ticket. - This egg will use the `main` branch of Open Ticket.
[**`openticket-egg-v4.2.0.json`**](openticket-egg-v4.2.0.json)
- This egg will always use Open Ticket `v4.2.0`. Open Ticket updates will not have an effect on this egg.
[**`openticket-egg-v4.1.3.json`**](openticket-egg-v4.1.3.json) [**`openticket-egg-v4.1.3.json`**](openticket-egg-v4.1.3.json)
- This egg will always use Open Ticket `v4.1.3`. Open Ticket updates will not have an effect on this egg. - This egg will always use Open Ticket `v4.1.3`. Open Ticket updates will not have an effect on this egg.
@@ -0,0 +1,62 @@
{
"_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO",
"meta": {
"version": "PTDL_v2",
"update_url": null
},
"exported_at": "2025-03-16T18:10:18+01:00",
"name": "Open Ticket (v4.2.0)",
"author": "support@dj-dj.be",
"description": "This is the official Pterodactyl egg for Open Ticket v4.2.0, the most advanced & customisable discord ticket bot that you will ever find! You can customise up to 300+ variables! This includes Html Transcripts, Advanced Plugins, Custom Embeds, Questions\/Modals, Stats & more!",
"features": null,
"docker_images": {
"ghcr.io\/parkervcp\/yolks:nodejs_20": "ghcr.io\/parkervcp\/yolks:nodejs_20"
},
"file_denylist": [],
"startup": "if [[ ! -z ${NODE_PACKAGES} ]]; then npm install ${NODE_PACKAGES}; fi; if [[ ! -z ${UNNODE_PACKAGES} ]]; then npm uninstall ${UNNODE_PACKAGES}; fi; if [ -f \/home\/container\/package.json ]; then npm install; fi; node \"\/home\/container\/index.js\" ${NODE_FLAGS};",
"config": {
"files": "{}",
"startup": "{\r\n \"done\": \"STARTUP INFO:\"\r\n}",
"logs": "{}",
"stop": "^C"
},
"scripts": {
"installation": {
"script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (v4.2.0)\r\n# Inspired by: Node.js Installation Script\r\n# \u00a9 DJdj Development\r\n\r\necho -e \"[OT INSTALLER] installing dependencies. please wait...\"\r\napt update\r\napt install -y git curl\r\n\r\necho -e \"[OT INSTALLER] updating npm. please wait...\"\r\nnpm install npm@latest --location=global\r\n\r\nmkdir -p \/mnt\/server\r\ncd \/mnt\/server\r\n\r\nBRANCH=\"v4.2.0\"\r\n\r\nif [ \"$(ls -A \/mnt\/server)\" ]; then\r\n echo -e \"[OT INSTALLER] \/mnt\/server directory is not empty.\"\r\n if [ -d .git ]; then\r\n echo -e \"[OT INSTALLER] .git directory exists\"\r\n if [ -f .git\/config ]; then\r\n echo -e \"[OT INSTALLER] loading info from git config\"\r\n ORIGIN=$(git config --get remote.origin.url)\r\n else\r\n echo -e \"[OT INSTALLER] files found with no git config\"\r\n echo -e \"[OT INSTALLER] closing out without touching things to not break anything\"\r\n exit 10\r\n fi\r\n fi\r\n\r\n if [ \"${ORIGIN}\" == \"https:\/\/github.com\/open-discord-bots\/open-ticket.git\" ]; then\r\n echo \"pulling latest from github\"\r\n git pull\r\n fi\r\nelse\r\n echo -e \"[OT INSTALLER] \/mnt\/server is empty.\"\r\n echo -e \"[OT INSTALLER] cloning files into repo.\"\r\n if [ -z ${BRANCH} ]; then\r\n echo -e \"[OT INSTALLER] cloning default branch\"\r\n git clone https:\/\/github.com\/open-discord-bots\/open-ticket.git .\r\n else\r\n echo -e \"[OT INSTALLER] cloning ${BRANCH}'\"\r\n git clone --single-branch --branch ${BRANCH} https:\/\/github.com\/open-discord-bots\/open-ticket.git .\r\n fi\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing Open Ticket node.js packages.\"\r\nif [ -f \/mnt\/server\/package.json ]; then\r\n \/usr\/local\/bin\/npm install --omit=dev\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing custom node.js packages.\"\r\nif [[ ! -z ${NODE_PACKAGES} ]]; then\r\n \/usr\/local\/bin\/npm install ${NODE_PACKAGES}\r\nfi\r\n\r\necho -e \"[OT INSTALLER] install complete!\"\r\nexit 0",
"container": "node:latest",
"entrypoint": "bash"
}
},
"variables": [
{
"name": "Additional Npm Packages",
"description": "Specify additional npm packages used by Open Ticket plugins. Use spaces to separate.",
"env_variable": "NODE_PACKAGES",
"default_value": "",
"user_viewable": false,
"user_editable": true,
"rules": "string|nullable",
"field_type": "text"
},
{
"name": "Startup Flags",
"description": "Start the bot with additional Open Ticket flags. Separate using spaces.\r\nA full reference list can be found in the documentation.",
"env_variable": "NODE_FLAGS",
"default_value": "",
"user_viewable": false,
"user_editable": true,
"rules": "string|nullable",
"field_type": "text"
},
{
"name": "Uninstall Npm Packages",
"description": "A list of npm packages to uninstall. Separate by spaces.",
"env_variable": "UNNODE_PACKAGES",
"default_value": "",
"user_viewable": false,
"user_editable": true,
"rules": "string|nullable",
"field_type": "text"
}
]
}
+1 -1
View File
@@ -4,7 +4,7 @@
<sub align="center">Related Projects:</sub><br> <sub align="center">Related Projects:</sub><br>
<a href="https://odplugins.dj-dj.be"><img src="https://apis.dj-dj.be/cdn/opendiscord/logo.png" alt="Open Discord" height="55px"></a><br><br> <a href="https://odplugins.dj-dj.be"><img src="https://apis.dj-dj.be/cdn/opendiscord/logo.png" alt="Open Discord" height="55px"></a><br><br>
<a href="https://discord.com/invite/26vT9wt3n3"><img alt="Discord Invite Link" src="https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord"></img></a> <a href="https://discord.com/invite/26vT9wt3n3"><img alt="Discord Invite Link" src="https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord"></img></a>
<a href="https://github.com/open-discord-bots/open-ticket/releases/tag/v4.1.3"><img alt="Open Ticket Version" src="https://img.shields.io/badge/version-4.1.3-brightgreen.svg?style=flat-square"></img></a> <a href="https://github.com/open-discord-bots/open-ticket/releases/tag/v4.2.0"><img alt="Open Ticket Version" src="https://img.shields.io/badge/version-4.2.0-brightgreen.svg?style=flat-square"></img></a>
<a href="https://otdocs.dj-dj.be"><img alt="Open Ticket Documentation" src="https://img.shields.io/badge/discord.js-v14-CB3837.svg?style=flat-square&logo=npm"></img></a> <a href="https://otdocs.dj-dj.be"><img alt="Open Ticket Documentation" src="https://img.shields.io/badge/discord.js-v14-CB3837.svg?style=flat-square&logo=npm"></img></a>
<a href="https://github.com/open-discord-bots/open-ticket/blob/main/LICENSE"><img alt="Open Ticket License" src="https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square"></img></a> <a href="https://github.com/open-discord-bots/open-ticket/blob/main/LICENSE"><img alt="Open Ticket License" src="https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square"></img></a>
<a href="https://otdocs.dj-dj.be"><img alt="Open Ticket Stars" src="https://img.shields.io/github/stars/djj123dj/open-ticket?color=yellow&label=stars&logo=github&style=flat-square"></img></a> <a href="https://otdocs.dj-dj.be"><img alt="Open Ticket Stars" src="https://img.shields.io/github/stars/djj123dj/open-ticket?color=yellow&label=stars&logo=github&style=flat-square"></img></a>
-125
View File
@@ -1,125 +0,0 @@
{
"_INFO":{
"support":"https://otdocs.dj-dj.be",
"discord":"https://discord.dj-dj.be",
"version":"open-ticket-v4.1.3"
},
"token":"INSERT_BOT_TOKEN (leave empty if using 'tokenFromENV')",
"tokenFromENV":false,
"mainColor":"#f8ba00",
"language":"english",
"prefix":"!ticket ",
"serverId":"DISCORD_SERVER_ID",
"globalAdmins":["DISCORD_ROLE_ID"],
"slashCommands":true,
"textCommands":true,
"status":{
"enabled":true,
"type":"listening OR watching OR playing OR custom",
"mode":"online OR invisible OR idle OR dnd",
"text":"/help",
"state":"Insert additional status text (or leave empty)"
},
"system":{
"preferSlashOverText":true,
"sendErrorOnUnknownCommand":true,
"questionFieldsInCodeBlock":true,
"displayFieldsWithQuestions":false,
"showGlobalAdminsInPanelRoles":false,
"disableVerifyBars":false,
"useRedErrorEmbeds":true,
"alwaysShowReason":false,
"emojiStyle":"before (OR after OR double OR disabled)",
"pinEmoji":"📌",
"replyOnTicketCreation":true,
"replyOnReactionRole":true,
"askPriorityOnTicketCreation":false,
"removeParticipantsOnClose":false,
"disableAutocloseAfterReopen":true,
"autodeleteRequiresClosedTicket":true,
"adminOnlyDeleteWithoutTranscript":true,
"allowCloseBeforeMessage":false,
"allowCloseBeforeAdminMessage":true,
"useTranslatedConfigChecker":true,
"pinFirstTicketMessage":false,
"enableTicketClaimButtons":true,
"enableTicketCloseButtons":true,
"enableTicketPinButtons":true,
"enableTicketDeleteButtons":true,
"enableTicketActionWithReason":true,
"enableDeleteWithoutTranscript":true,
"logs":{
"enabled":false,
"channel":"DISCORD_CHANNEL_ID"
},
"limits":{
"enabled":true,
"globalMaximum":50,
"userMaximum":3
},
"channelTopic":{
"showOptionName":true,
"showOptionDescription":false,
"showOptionTopic":true,
"showPriority":false,
"showClosed":true,
"showClaimed":false,
"showPinned":false,
"showCreator":false,
"showParticipants":false
},
"permissions":{
"help":"everyone (OR admin OR none OR role id)",
"panel":"admin (OR everyone OR none OR role id)",
"ticket":"none (OR admin OR everyone OR role id)",
"close":"everyone (OR admin OR none OR role id)",
"delete":"admin (OR everyone OR none OR role id)",
"reopen":"everyone (OR admin OR none OR role id)",
"claim":"admin (OR everyone OR none OR role id)",
"unclaim":"admin (OR everyone OR none OR role id)",
"pin":"admin (OR everyone OR none OR role id)",
"unpin":"admin (OR everyone OR none OR role id)",
"move":"admin (OR everyone OR none OR role id)",
"rename":"admin (OR everyone OR none OR role id)",
"add":"admin (OR everyone OR none OR role id)",
"remove":"admin (OR everyone OR none OR role id)",
"blacklist":"admin (OR everyone OR none OR role id)",
"stats":"everyone (OR admin OR none OR role id)",
"clear":"admin (OR everyone OR none OR role id)",
"autoclose":"admin (OR everyone OR none OR role id)",
"autodelete":"admin (OR everyone OR none OR role id)",
"transfer":"admin (OR everyone OR none OR role id)",
"topic":"admin (OR everyone OR none OR role id)",
"priority":"admin (OR everyone OR none OR role id)"
},
"messages":{
"creation":{"dm":false,"logs":true},
"closing":{"dm":false,"logs":true},
"deleting":{"dm":false,"logs":true},
"reopening":{"dm":false,"logs":true},
"claiming":{"dm":false,"logs":true},
"pinning":{"dm":false,"logs":true},
"adding":{"dm":false,"logs":true},
"removing":{"dm":false,"logs":true},
"renaming":{"dm":false,"logs":true},
"moving":{"dm":false,"logs":true},
"blacklisting":{"dm":false,"logs":true},
"transferring":{"dm":false,"logs":true},
"topicChange":{"dm":false,"logs":true},
"priorityChange":{"dm":false,"logs":true},
"reactionRole":{"dm":false,"logs":true}
}
}
}
+175
View File
@@ -0,0 +1,175 @@
/*
* Hi there! Thank you for installing Open Ticket.
* ----------------------------------------------
* If you need any assistance with configuring the bot,
* feel free to use the documentation or join our Discord server:
* https://otdocs.dj-dj.be
* https://discord.dj-dj.be
* ----------------------------------------------
* SETUP:
* 1. Install the required dependencies using the command: "npm install"
* 2. Configure the bot in one of the following ways:
* a. (easy) Using the Quick Setup CLI Tool
* b. (difficult) Using the JSON files in `./config/`
*
* Start the Quick Setup CLI Tool using the command: "npm run setup"
* After configuration, start the bot using the command: "npm start"
*
* Good luck! DJj123dj & contributors
*/
{
"_CONFIG_VERSION":"open-ticket-v4.2.0",
/* Load the bot token from .env or the "token" field below. Leave "token" empty if using "tokenFromENV". */
"token":"INSERT_BOT_TOKEN",
"tokenFromENV":false,
"mainColor":"#f8ba00", //Hex color used in most embeds
"language":"english", //Visit README.md for list
"prefix":"!ticket ", //Prefix used in text commands
"serverId":"DISCORD_SERVER_ID",
"globalAdmins":["DISCORD_ROLE_ID"], //Have access to all commands
/* Enable/disable text or slash commands. */
"slashCommands":true,
"textCommands":true,
/* Configure the status of the bot. */
"status":{
"enabled":true,
"type":"listening", //Choices: listening, watching, playing, custom
"mode":"online", //Choices: online, invisible, idle, dnd
"text":"/help",
"state":"" //Additional text (Leave empty to disable)
},
/* Send ticket logs to a channel or in DM of the ticket creator. */
"logs":{
"enabled":false,
"channel":"DISCORD_CHANNEL_ID",
"logMessages":{
"creation":{"dm":false,"logs":true},
"closing":{"dm":false,"logs":true},
"deleting":{"dm":false,"logs":true},
"reopening":{"dm":false,"logs":true},
"claiming":{"dm":false,"logs":true},
"pinning":{"dm":false,"logs":true},
"adding":{"dm":false,"logs":true},
"removing":{"dm":false,"logs":true},
"renaming":{"dm":false,"logs":true},
"moving":{"dm":false,"logs":true},
"blacklisting":{"dm":false,"logs":true},
"transferring":{"dm":false,"logs":true},
"topicChange":{"dm":false,"logs":true},
"priorityChange":{"dm":false,"logs":true},
"reactionRole":{"dm":false,"logs":true}
}
},
/* A large collection of settings for the ticket system. */
"ticketSystem":{
"preferSlashOverText":true, //Show slashcmds in help menu's
"sendErrorOnUnknownCommand":true, //Send error when command not found
"questionFieldsInCodeBlock":true, //Put question answers in code blocks
"displayFieldsWithQuestions":false, //Display embed fields together with question answers
"showGlobalAdminsInPanelRoles":false, //Include "globalAdmins" in panel admin lists
"disableVerifyBars":false, //Disable the (❌/✅) buttons
"useRedErrorEmbeds":true, //Make errors embeds always red
"alwaysShowReason":false, //Show reason even if none is provided
"emojiStyle":"before", //The style of emoji's in embeds. Choices: before, after, double, disabled
"pinEmoji":"📌", //Channel emoji of pinned tickets (Leave empty to disable)
"closeEmoji":"🔒", //Channel emoji of closed tickets (Leave empty to disable)
"replyOnTicketCreation":true, //Reply with a msg when a ticket is created
"replyOnReactionRole":true, //Reply with a msg when a reaction role is used
"askPriorityOnTicketCreation":true, //Show a dropdown to select priority
"removeParticipantsOnClose":false, //Remove non-admins when ticket is closed
"disableAutocloseAfterReopen":true, //Disable autoclose after ticket got reopened
"autodeleteRequiresClosedTicket":true, //A ticket must be closed before autodelete works
"adminOnlyDeleteWithoutTranscript":true, //Only allow "globalAdmins" to delete a ticket without transcript
"allowCloseBeforeMessage":false, //Allow closing before a message is sent
"allowCloseBeforeAdminMessage":true, //Allow closing before an admin has sent a message
"useTranslatedConfigChecker":true, //Translate config errors in the console
"pinFirstTicketMessage":true, //Pin the ticket message to the channel
/* Enable/disable certain buttons & features of the bot. */
"enableTicketClaimButtons":true,
"enableTicketCloseButtons":true,
"enableTicketPinButtons":true,
"enableTicketDeleteButtons":true,
"enableTicketActionWithReason":true,
"enableDeleteWithoutTranscript":true, //Allow deleting tickets without transcript
"enableCreateTicketForOtherUser":true, //Allow creating tickets for other users
/* Set the maximum amount of simultaneous tickets. */
"limits":{
"enabled":true,
"globalMaximum":50,
"userMaximum":3
},
/* Choose which data is shown in the channel topic. */
"channelTopic":{
"showOptionName":true,
"showOptionDescription":false,
"showOptionTopic":true,
"showPriority":false,
"showClosed":true,
"showClaimed":false,
"showPinned":false,
"showCreator":false,
"showParticipants":false
},
/* Move closed tickets to a separate category. */
"closedCategory":{
"enabled":false,
"categoryId":"DISCORD_CATEGORY_ID"
},
/* Create tickets in a backup category when the original category exceeds 50 channels. */
"backupCategory":{
"enabled":false,
"categoryId":"DISCORD_CATEGORY_ID"
},
/* Move claimed tickets to a matching category of the user that claimed the ticket. Set to empty list [] to disable. */
"claimedCategories":[
{"user":"DISCORD_USER_ID","category":"DISCORD_CATEGORY_ID"}
]
},
/*
* Set permissions for each individual command, button or action.
* CHOICES:
* >> "none" -> Command disabled
* >> "everyone" -> Allowed for everyone
* >> "admin" -> Global & ticket admins only
* >> "DISCORD_ROLE_ID" -> Custom role only
*/
"permissions":{
"help":"everyone",
"panel":"admin",
"ticket":"none",
"close":"everyone",
"delete":"admin",
"reopen":"everyone",
"claim":"admin",
"unclaim":"admin",
"pin":"admin",
"unpin":"admin",
"move":"admin",
"rename":"admin",
"add":"admin",
"remove":"admin",
"blacklist":"admin",
"stats":"everyone",
"clear":"admin",
"autoclose":"admin",
"autodelete":"admin",
"transfer":"admin",
"topic":"admin",
"priority":"admin",
"transcripts":"admin"
}
}
-126
View File
@@ -1,126 +0,0 @@
[
{
"id":"example-ticket",
"name":"Question",
"description":"Want to tell us something? Create this ticket for general questions for our support team. (leave empty to disable)",
"type":"ticket",
"button":{
"emoji":"🎫 (leave empty to disable)",
"label":"question (leave empty to disable)",
"color":"gray OR red OR green OR blue"
},
"ticketAdmins":["DISCORD_ROLE_ID"],
"readonlyAdmins":["DISCORD_ROLE_ID"],
"allowCreationByBlacklistedUsers":false,
"questions":["example-question-1","example-question-2"],
"channel":{
"prefix":"question-",
"suffix":"user-name OR user-id OR random-number OR random-hex OR counter-dynamic OR counter-fixed",
"category":"category id (leave empty to disable)",
"closedCategory":"category id (leave empty to disable)",
"backupCategory":"category id (leave empty to disable)",
"claimedCategory":[
{"user":"USER_ID","category":"CATEGORY_ID"}
],
"topic":"This is the ticket topic shown in the channel. (leave empty to disable)"
},
"dmMessage":{
"enabled":false,
"text":"",
"embed":{
"enabled":false,
"title":"Question Ticket (leave empty to disable)",
"description":"Thank you for creating a ticket in our server. We will try to help you as soon as possible. (leave empty to disable)",
"customColor":"#f8ab00 (leave empty to disable)",
"image":"https://www.example.com/image.png (leave empty to disable)",
"thumbnail":"https://www.example.com/image.png (leave empty to disable)",
"fields":[
{"name":"Field name","value":"Field value","inline":false}
],
"timestamp":false
}
},
"ticketMessage":{
"enabled":true,
"text":"",
"embed":{
"enabled":true,
"title":"Question Ticket",
"description":"Thank you for creating a ticket in our server.\nOur support team will assist you as soon as possible. (leave empty to disable)",
"customColor":"#f8ab00 (leave empty to disable)",
"image":"https://www.example.com/image.png (leave empty to disable)",
"thumbnail":"https://www.example.com/image.png (leave empty to disable)",
"fields":[
{"name":"Field name","value":"Field value","inline":false}
],
"timestamp":false
},
"ping":{
"@here":true,
"@everyone":false,
"custom":["DISCORD_ROLE_ID"]
}
},
"autoclose":{
"enableInactiveHours":false,
"inactiveHours":24,
"enableUserLeave":false,
"disableOnClaim":false
},
"autodelete":{
"enableInactiveDays":false,
"inactiveDays":7,
"enableUserLeave":false,
"disableOnClaim":false
},
"cooldown":{
"enabled":false,
"cooldownMinutes":10
},
"limits":{
"enabled":false,
"globalMaximum":20,
"userMaximum":3
},
"slowMode":{
"enabled":false,
"slowModeSeconds":20
}
},
{
"id":"example-website",
"name":"Website",
"description":"Take a look at our amazing website by clicking the button.",
"type":"website",
"button":{
"emoji":"😃",
"label":"Visit Website"
},
"url":"https://www.dj-dj.be"
},
{
"id":"example-role",
"name":"Update Ping",
"description":"Click here to receive notifications about updates.",
"type":"role",
"button":{
"emoji":"📢",
"label":"Update Ping",
"color":"gray OR red OR green OR blue"
},
"roles":["DISCORD_ROLE_ID"],
"mode":"add&remove OR remove OR add",
"removeRolesOnAdd":["DISCORD_ROLE_ID"],
"addOnMemberJoin":false
}
]
+165
View File
@@ -0,0 +1,165 @@
/*
* OPEN TICKET BUTTON OPTIONS
* ----------------------------------------------
* Create customizable ticket, website, reaction-role or sub-panel button options.
* Up to 25 options can be added to each panel in (config/panels.jsonc)
* There are 4 types of options available: ticket, website, role, sub-panel
*
* TIP: Create new options by copying everything between and including the {...} brackets of an option. Paste it after the last option and make sure that they are seperated by a comma.
*/
[
{
/* A ticket option creates a button to open a ticket. */
"id":"example-ticket",
"name":"Question",
"description":"Want to tell us something? Create this ticket for general questions for our support team.", //Leave empty to disable
"type":"ticket",
"button":{
/* Configure the button style of this option. At least one of "emoji" or "label" must be provided. */
"emoji":"🎫",
"label":"Question",
"color":"gray" //Choices: gray, red, green, blue
},
/* Add up to 5 modal questions IDs from (config/questions.jsonc). */
"questions":["example-question-1","example-question-2"],
"ticketAdmins":["DISCORD_ROLE_ID"],
"readonlyAdmins":["DISCORD_ROLE_ID"],
"allowCreationByBlacklistedUsers":false,
"channel":{
/* Configure the name, topic and category of the ticket option. */
"prefix":"question-",
"suffix":"user-name", //Choices: user-name, user-id, random-number, random-hex, counter-dynamic, counter-fixed
"category":"DISCORD_CATEGORY_ID", //Leave empty to disable
"topic":"The ticket topic shown in the channel." //Leave empty to disable
},
"dmMessage":{
/* Send a customisable message in DM when creating a ticket. */
"enabled":false,
"text":"", //Leave empty to disable
"embed":{
"enabled":false,
"title":"Question Ticket", //Leave empty to disable
"description":"Thank you for creating a ticket in our server. We will try to help you as soon as possible.", //Leave empty to disable
"customColor":"#f8ab00", //Leave empty to use default color
"image":"", //Image URL. Leave empty to disable
"thumbnail":"", //Image URL. Leave empty to disable
/* Embed fields. Set to empty list [] to disable. */
"fields":[
{"name":"Field name","value":"Field value","inline":false}
],
"timestamp":false
}
},
"ticketMessage":{
/* Send a customisable message in the ticket with close, claim, delete, ... buttons. */
"enabled":true,
"text":"", //Leave empty to disable
"embed":{
"enabled":true,
"title":"Question Ticket", //Leave empty to disable
"description":"Thank you for creating a ticket in our server.\nOur support team will assist you as soon as possible. (leave empty to disable)", //Leave empty to disable
"customColor":"#f8ab00 (leave empty to disable)", //Leave empty to use default color
"image":"https://www.example.com/image.png (leave empty to disable)", //Image URL. Leave empty to disable
"thumbnail":"https://www.example.com/image.png (leave empty to disable)", //Image URL. Leave empty to disable
/* Embed fields. Set to empty list [] to disable. */
"fields":[
{"name":"Field name","value":"Field value","inline":false}
],
"timestamp":false
},
"ping":{
/* Customise the user & role mentions of this ticket message. */
"@here":true,
"@everyone":false,
"custom":["DISCORD_ROLE_ID"]
}
},
"autoclose":{
/* Autoclose this ticket after a period of inactivity or when the creator leaves the server. */
"enableInactiveHours":false,
"inactiveHours":24,
"enableUserLeave":false,
"disableOnClaim":false
},
"autodelete":{
/* Autodelete this ticket after a period of inactivity or when the creator leaves the server. */
"enableInactiveDays":false,
"inactiveDays":7,
"enableUserLeave":false,
"disableOnClaim":false
},
"cooldown":{
/* Users must wait a certain period before being able to create another ticket of this type. */
"enabled":false,
"cooldownMinutes":10
},
"limits":{
/* Set the maximum amount of simultaneous tickets of this option. */
"enabled":false,
"globalMaximum":20,
"userMaximum":3
},
"slowMode":{
/* Enable slow-mode in the ticket channel. */
"enabled":false,
"slowModeSeconds":20
}
},
{
/* A website option creates a button with a URL to an external website. */
"id":"example-website",
"name":"Website",
"description":"Take a look at our amazing website.", //Leave empty to disable
"type":"website",
"button":{
/* Configure the button style of this option. At least one of "emoji" or "label" must be provided. */
"emoji":"😃",
"label":"Visit Website"
},
"url":"https://www.dj-dj.be"
},
{
/* A reaction-role option creates a button for members to choose roles. */
"id":"example-role",
"name":"Update Ping",
"description":"Receive notifications about updates in our server.", //Leave empty to disable
"type":"role",
"button":{
/* Configure the button style of this option. At least one of "emoji" or "label" must be provided. */
"emoji":"📢",
"label":"Update Ping",
"color":"gray" //Choices: gray, red, green, blue
},
"roles":["DISCORD_ROLE_ID"],
"mode":"add&remove OR remove OR add", //What to do with the roles. Choices: add&remove, add, remove
"removeRolesOnAdd":["DISCORD_ROLE_ID"], //Remove these old roles when new roles are added.
"addOnMemberJoin":false //Add these roles automatically when joining the server.
},
{
/* A sub-panel option creates a button which sends another panel for additional options. */
"id":"example-sub-panel",
"name":"Example Sub-Panel",
"description":"This is an example of how to implement a sub-panel in Open Ticket.", //Leave empty to disable
"type":"sub-panel",
"button":{
/* Configure the button style of this option. At least one of "emoji" or "label" must be provided. */
"emoji":"📋",
"label":"Sub-Panel Example",
"color":"gray" //Choices: gray, red, green, blue
},
"subPanelId":"example-panel" //Choose a panel ID from (config/panels.jsonc)
}
]
-39
View File
@@ -1,39 +0,0 @@
[
{
"id":"example-embed",
"name":"Example Embed",
"dropdown":false,
"options":["example-ticket","example-website","example-role"],
"text":"",
"embed":{
"enabled":true,
"title":"Tickets:",
"description":"Create a ticket by selecting one of the options below. Once selected, a private ticket will be created for you and our support team will be able to assist you directly.",
"customColor":"#f8ab00 (leave empty to disable)",
"url":"https://openticket.dj-dj.be (leave empty to disable)",
"image":"https://www.example.com/image.png (leave empty to disable)",
"thumbnail":"https://www.example.com/image.png (leave empty to disable)",
"footer":"Open Ticket v4.1.3 (leave empty to disable)",
"fields":[
{"name":"Field name","value":"Field value","inline":false}
],
"timestamp":false
},
"settings":{
"dropdownPlaceholder":"Choose a ticket type",
"enableMaxTicketsWarningInText":false,
"enableMaxTicketsWarningInEmbed":true,
"describeOptionsLayout":"simple OR normal OR detailed",
"describeOptionsCustomTitle":"",
"describeOptionsInText":false,
"describeOptionsInEmbedFields":true,
"describeOptionsInEmbedDescription":false
}
}
]
+57
View File
@@ -0,0 +1,57 @@
/*
* OPEN TICKET PANELS
* ----------------------------------------------
* Create customizable panel messages with buttons or a dropdown.
* Add up to 25 options to this panel from (config/options.jsonc)
* Panels can be customised with text, images, colors and more.
*
* Spawn the panel in Discord using: /panel <id>
*
* TIP: Create new panels by copying everything between and including the {...} brackets of an panel. Paste it after the last panel and make sure that they are seperated by a comma.
*/
[
{
/* A panel is creates a message with up to 25 options as buttons or dropdown. */
"id":"example-panel",
"name":"Example Panel",
"dropdown":false,
/* Add up to 5 option IDs from (config/options.jsonc). */
"options":["example-ticket","example-website","example-role"],
"text":"", //Leave empty to disable
"embed":{
"enabled":true,
"title":"Tickets:", //Leave empty to disable
"description":"Create a ticket by selecting one of the options below. Once selected, a private ticket will be created for you and our support team will be able to assist you directly.", //Leave empty to disable
"customColor":"#f8ab00", //Leave empty to use default color
"url":"", //URL. Leave empty to disable
"image":"", //Image URL. Leave empty to disable
"thumbnail":"", //Image URL. Leave empty to disable
"footer":"Open Ticket v4.2.0", //Leave empty to disable
/* Embed fields. Set to empty list [] to disable. */
"fields":[
{"name":"Field name","value":"Field value","inline":false}
],
"timestamp":false
},
"settings":{
"dropdownPlaceholder":"Create a ticket...", //Leave empty to use default.
"maximumButtonsPerRow":5,
/* Display the maximum amount of tickets per user. */
"enableMaxTicketsWarningInText":false,
"enableMaxTicketsWarningInEmbed":true,
/* Automatically generate option descriptions from (config/options.jsonc). */
"describeOptionsLayout":"normal", //Choices: simple, normal, detailed
"describeOptionsCustomTitle":"",
"describeOptionsInText":false,
"describeOptionsInEmbedFields":true,
"describeOptionsInEmbedDescription":false
}
}
]
-28
View File
@@ -1,28 +0,0 @@
[
{
"id":"example-question-1",
"name":"Example Question 1",
"type":"short",
"required":true,
"placeholder":"An example short text question.",
"length":{
"enabled":false,
"min":0,
"max":1000
}
},
{
"id":"example-question-2",
"name":"Example Question 2",
"type":"paragraph",
"required":false,
"placeholder":"An example paragraph text question.",
"length":{
"enabled":false,
"min":0,
"max":1000
}
}
]
+102
View File
@@ -0,0 +1,102 @@
/*
* OPEN TICKET MODAL QUESTIONS
* ----------------------------------------------
* Create customizable modal questions that will be shown before creating a ticket.
* Each ticket option (config/options.jsonc) can contain a maximum of 5 questions.
* There are 6 types of questions available: short, paragraph, dropdown, radio-select, checkbox-select, text-display
*
* TIP: Create new questions by copying everything between and including the {...} brackets of a question. Paste it after the last question and make sure that they are seperated by a comma.
*/
[
{
/* A short text input modal question. */
"id":"example-question-1",
"name":"Example Question 1",
"description":"", //Leave empty to disable
"type":"short",
"required":true,
"placeholder":"Insert answer...",
"length":{
/* Configure length limits for the answer. */
"enabled":false,
"min":0,
"max":1000
}
},
{
/* A paragraph text input modal question. */
"id":"example-question-2",
"name":"Example Question 2",
"description":"", //Leave empty to disable
"type":"paragraph",
"required":false,
"placeholder":"Insert answer...",
"length":{
/* Configure length limits for the answer. */
"enabled":false,
"min":0,
"max":1000
}
},
{
/* A dropdown menu input modal question with up to 25 choices. "emoji" & "description" fields are optional. */
"id":"example-question-3",
"name":"Example Question 3",
"description":"This is a dropdown question.", //Leave empty to disable
"type":"dropdown",
"required":false,
"placeholder":"Choose your answer...",
"choices":[
{"title":"Choice A","description":"Apple","emoji":"🍎"},
{"title":"Choice B","description":"Banana","emoji":"🍌"},
{"title":"Choice C","description":"Orange","emoji":"🍊"},
{"title":"Choice D","description":"Kiwi","emoji":"🥝"}
]
},
{
/* A radio select input modal question with up to 10 choices. */
"id":"example-question-4",
"name":"Example Question 4",
"description":"This is a radio select question.", //Leave empty to disable
"type":"radio-select",
"required":true,
"choices":[
{"title":"Choice A","description":"Up","selectedByDefault":false},
{"title":"Choice B","description":"Down","selectedByDefault":false},
{"title":"Choice C","description":"Left","selectedByDefault":false},
{"title":"Choice D","description":"Right","selectedByDefault":false}
]
},
{
/* A checkbox select input modal question with up to 10 choices. */
"id":"example-question-5",
"name":"Example Question 5",
"description":"This is a checkbox select question.", //Leave empty to disable
"type":"checkbox-select",
"required":true,
"limits":{
/* Configure checkbox amount limits for the answer. */
"enabled":false,
"min":0,
"max":10
},
"choices":[
{"title":"Choice A","description":"Happiness","selectedByDefault":false},
{"title":"Choice B","description":"Anger","selectedByDefault":false},
{"title":"Choice C","description":"Sadness","selectedByDefault":false},
{"title":"Choice D","description":"Fear","selectedByDefault":false}
]
},
{
/* Show text in a modal to provide extra details or explain questions. */
"id":"example-text-display",
"type":"text-display",
"textContents":"This is a text display. It isn't a question, but allows you to display additional details."
}
]
-55
View File
@@ -1,55 +0,0 @@
{
"general":{
"enabled":false,
"enableChannel":false,
"enableCreatorDM":false,
"enableParticipantDM":false,
"enableActiveAdminDM":false,
"enableEveryAdminDM":false,
"channel":"DISCORD_TRANSCRIPT_CHANNEL_ID (leave empty to disable)",
"mode":"html OR text"
},
"embedSettings":{
"customColor":"#f8ab00 (leave empty to disable)",
"listAllParticipants":false,
"includeTicketStats":false
},
"textTranscriptStyle":{
"layout":"simple OR normal OR detailed",
"includeStats":true,
"includeIds":false,
"includeEmbeds":true,
"includeFiles":true,
"includeBotMessages":true,
"fileMode":"custom OR channel-name OR channel-id OR user-name OR user-id",
"customFileName":"transcript"
},
"htmlTranscriptStyle":{
"background":{
"enableCustomBackground":false,
"backgroundColor":"#f8ba00 (leave empty to disable)",
"backgroundImage":"https://www.example.com/image.png (leave empty to disable)"
},
"header":{
"enableCustomHeader":false,
"backgroundColor":"#202225",
"decoColor":"#f8ba00",
"textColor":"#ffffff"
},
"stats":{
"enableCustomStats":false,
"backgroundColor":"#202225",
"keyTextColor":"#737373",
"valueTextColor":"#ffffff",
"hideBackgroundColor":"#40444a",
"hideTextColor":"#ffffff"
},
"favicon":{
"enableCustomFavicon":false,
"imageUrl":"https://t.dj-dj.be/favicon.png"
}
}
}
+70
View File
@@ -0,0 +1,70 @@
/*
* OPEN TICKET TRANSCRIPTS
* ----------------------------------------------
* Enable transcript creation when tickets are deleted. There are 2 available transcript types: HTML & Text
*
* HTML Transcripts (recommended):
* Generate transcripts as HTML files to view in the browser. No server or domain required. HTML Transcripts use an external service to process and host the transcripts.
*
* Text Transcripts:
* Generate transcripts as simple .txt files with limited details. Processing happens fully local.
*/
{
"general":{
"enabled":false,
/* Choose which users and channel get the generated transcript. */
"enableChannel":false,
"enableCreatorDM":false,
"enableParticipantDM":false,
"enableActiveAdminDM":false,
"enableEveryAdminDM":false,
"channel":"DISCORD_CHANNEL_ID", //Where to send transcripts. Leave empty when disabled.
"mode":"html" //The type of transcript to use. Choices: html, text
},
"embedSettings":{
/* Customise the embed which contains the generated transcript file or URL. */
"customColor":"#f8ab00", //Leave empty to use default color
"listAllParticipants":false,
"includeTicketStats":false
},
"textTranscriptStyle":{
/* Customise layout of the text transcripts. */
"layout":"normal", //Choices: simple, normal, detailed
"includeStats":true,
"includeIds":false,
"includeEmbeds":true,
"includeFiles":true,
"includeBotMessages":true,
"fileMode":"custom", //How to name the transcript file? Choices: custom, channel-name, channel-id, user-name, user-id
"customFileName":"transcript" //Custom filename without extension
},
"htmlTranscriptStyle":{
/* Customise layout of the HTML transcripts. */
"background":{
"enableCustomBackground":false,
"backgroundColor":"#f8ba00", //Leave empty to use Open Ticket color (#f8ba00)
"backgroundImage":"https://www.example.com/image.png" //Image URL to fill entire background. Leave empty to disable
},
"header":{
"enableCustomHeader":false,
"backgroundColor":"#202225",
"decoColor":"#f8ba00",
"textColor":"#ffffff"
},
"stats":{
"enableCustomStats":false,
"backgroundColor":"#202225",
"keyTextColor":"#737373",
"valueTextColor":"#ffffff",
"hideBackgroundColor":"#40444a",
"hideTextColor":"#ffffff"
},
"favicon":{
"enableCustomFavicon":false,
"imageUrl":"https://t.dj-dj.be/favicon.png"
}
}
}
+1
View File
@@ -0,0 +1 @@
[]
+1 -1
View File
@@ -13,7 +13,7 @@ const flags = [
██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║ ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║
╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║ ╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║
╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝
v4.1.3 - Made by DJj123dj & Contributors v4.2.0 - Made by DJj123dj & Contributors
Discord: https://discord.dj-dj.be Discord: https://discord.dj-dj.be
Docs: https://otdocs.dj-dj.be Docs: https://otdocs.dj-dj.be
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["palestinian"], "translators":["palestinian"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Arabic", "language":"Arabic",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["HanumeshGupta"], "translators":["HanumeshGupta"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Bengali", "language":"Bengali",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["guillee3"], "translators":["guillee3"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Catalan", "language":"Catalan",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["DJj123dj"], "translators":["DJj123dj"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Custom", "language":"Custom",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["spyeye_"], "translators":["spyeye_"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Czech", "language":"Czech",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["the_gamer"], "translators":["the_gamer"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Danish", "language":"Danish",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["DJj123dj"], "translators":["DJj123dj"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Dutch", "language":"Dutch",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["DJj123dj"], "translators":["DJj123dj"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"English", "language":"English",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["iamnotmega","ChatGPT"], "translators":["iamnotmega","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Estonian", "language":"Estonian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["iamnotmega","ChatGPT"], "translators":["iamnotmega","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Finnish", "language":"Finnish",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["guillee3"], "translators":["guillee3"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"French", "language":"French",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["benzorich"], "translators":["benzorich"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"German", "language":"German",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"], "translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Greek", "language":"Greek",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["challenger_nova"], "translators":["challenger_nova"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Hindi", "language":"Hindi",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["Kornel0706"], "translators":["Kornel0706"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Hungarian", "language":"Hungarian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["erxg"], "translators":["erxg"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Indonesian", "language":"Indonesian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["fraden1mvp.","imperatorix_17"], "translators":["fraden1mvp.","imperatorix_17"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Italian", "language":"Italian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"], "translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Japanese", "language":"Japanese",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"], "translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Korean", "language":"Korean",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"], "translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Kurdish", "language":"Kurdish",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["NoOneNook"], "translators":["NoOneNook"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Latvian", "language":"Latvian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["TsgIndrius"], "translators":["TsgIndrius"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Lithuanian", "language":"Lithuanian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["NoOneNook"], "translators":["NoOneNook"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Norwegian", "language":"Norwegian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["dysashop","zhavis"], "translators":["dysashop","zhavis"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Persian", "language":"Persian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["DanoGlez"], "translators":["DanoGlez"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Polish", "language":"Polish",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["quiradon"], "translators":["quiradon"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Portuguese", "language":"Portuguese",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["SankeDev"], "translators":["SankeDev"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Romanian", "language":"Romanian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["NoOneNook"], "translators":["NoOneNook"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Russian", "language":"Russian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"], "translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Simplified Chainese", "language":"Simplified Chainese",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"], "translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Solvenian", "language":"Solvenian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["Redactado","Josuens"], "translators":["Redactado","Josuens"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Spanish", "language":"Spanish",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["NoOneNook"], "translators":["NoOneNook"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Svenska", "language":"Svenska",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"], "translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Tamil", "language":"Tamil",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["modshd"], "translators":["modshd"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Thai", "language":"Thai",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["me.october"], "translators":["me.october"],
"lastedited":"10/03/2026", "lastedited":"10/03/2026",
"language":"Traditional Chinese", "language":"Traditional Chinese",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["palestinian"], "translators":["palestinian"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Turkish", "language":"Turkish",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["Anderskiy"], "translators":["Anderskiy"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Ukrainian", "language":"Ukrainian",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"_TRANSLATION":{ "_TRANSLATION":{
"otversion":"v4.1.3", "otversion":"v4.2.0",
"translators":["ngocdiep2006"], "translators":["ngocdiep2006"],
"lastedited":"16/02/2026", "lastedited":"16/02/2026",
"language":"Vietnamese", "language":"Vietnamese",
+4 -4
View File
@@ -1,7 +1,7 @@
{ {
"name": "open-ticket", "name": "open-ticket",
"author": "DJdj Development", "author": "DJdj Development",
"version": "4.1.3", "version": "4.2.0",
"description": "The most advanced open-source discord ticket bot with HTML transcripts, plugins, questions, claiming, pinning & more! Using discord.js v14 & JSON database! ", "description": "The most advanced open-source discord ticket bot with HTML transcripts, plugins, questions, claiming, pinning & more! Using discord.js v14 & JSON database! ",
"keywords": [ "keywords": [
"ticket-bot", "ticket-bot",
@@ -26,12 +26,12 @@
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"dependencies": { "dependencies": {
"@discordjs/rest": "^2.6.1", "@discordjs/rest": "^2.6.1",
"@open-discord-bots/framework": "^0.4.0", "@open-discord-bots/framework": "^0.4.2",
"@types/node": "^22.5.0", "@types/node": "^22.5.0",
"@types/terminal-kit": "^2.5.7", "@types/terminal-kit": "^2.5.7",
"ansis": "^4.2.0", "ansis": "^4.2.0",
"discord.js": "^14.26.3", "discord.js": "^14.26.4",
"formatted-json-stringify": "^1.3.1", "formatted-json-stringify": "^1.3.2",
"terminal-kit": "^3.1.2", "terminal-kit": "^3.1.2",
"typescript": "^6.0.3" "typescript": "^6.0.3"
}, },
+2 -2
View File
@@ -49,14 +49,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason,data} = params const {guild,channel,user,ticket,reason,data} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.adding.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.adding.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"add",reason,additionalData:data}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.adding.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) if (creator && generalConfig.data.logs.logMessages.adding.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"add",reason,additionalData:data}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,data} = params const {guild,channel,user,ticket,data} = params
+5 -3
View File
@@ -46,8 +46,9 @@ export async function registerActions(){
const {guild,user,channel,option,ticket,currentCategoryId} = params const {guild,user,channel,option,ticket,currentCategoryId} = params
if (!ticket) return if (!ticket) return
if (!ticket.get("opendiscord:closed").value) return if (!ticket.get("opendiscord:closed").value) return
if (!generalConfig.data.ticketSystem.closedCategory.enabled) return
const closeCategoryId = option.get("opendiscord:channel-category-closed").value const closeCategoryId = generalConfig.data.ticketSystem.closedCategory.categoryId
if (!closeCategoryId) return if (!closeCategoryId) return
const closeCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,closeCategoryId) const closeCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,closeCategoryId)
if (closeCategory){ if (closeCategory){
@@ -74,7 +75,7 @@ export async function registerActions(){
if (!ticket) return if (!ticket) return
if (!ticket.get("opendiscord:claimed").value) return if (!ticket.get("opendiscord:claimed").value) return
const claimedCategoryIds = option.get("opendiscord:channel-categories-claimed").value const claimedCategoryIds = generalConfig.data.ticketSystem.claimedCategories
const claimCategoryId = claimedCategoryIds.find((c) => c.user == user.id)?.category const claimCategoryId = claimedCategoryIds.find((c) => c.user == user.id)?.category
if (!claimCategoryId) return if (!claimCategoryId) return
const claimCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,claimCategoryId) const claimCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,claimCategoryId)
@@ -101,8 +102,9 @@ export async function registerActions(){
const {guild,user,channel,option,ticket,currentCategoryId} = params const {guild,user,channel,option,ticket,currentCategoryId} = params
if (!instance.newCategory || !instance.newCategoryId || !instance.shouldChangeCategory) return if (!instance.newCategory || !instance.newCategoryId || !instance.shouldChangeCategory) return
if (instance.newCategory.children.cache.size < 50) return if (instance.newCategory.children.cache.size < 50) return
if (!generalConfig.data.ticketSystem.backupCategory.enabled) return
const backupCategoryId = option.get("opendiscord:channel-category-backup").value const backupCategoryId = generalConfig.data.ticketSystem.backupCategory.categoryId
if (!backupCategoryId) return if (!backupCategoryId) return
const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,backupCategoryId) const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,backupCategoryId)
if (backupCategory){ if (backupCategory){
+1 -1
View File
@@ -19,7 +19,7 @@ export async function registerActions(){
const baseChannelName = (channelRenamed) ? channelRenamed : channelPrefix+channelSuffix const baseChannelName = (channelRenamed) ? channelRenamed : channelPrefix+channelSuffix
//calculate status emojis //calculate status emojis
const pinEmoji = (ticket && ticket.get("opendiscord:pinned").value) ? generalConfig.data.system.pinEmoji : "" const pinEmoji = (ticket && ticket.get("opendiscord:pinned").value) ? generalConfig.data.ticketSystem.pinEmoji : ""
const priorityEmoji = (ticket) ? (opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? "") : "" const priorityEmoji = (ticket) ? (opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? "") : ""
instance.newChannelName = pinEmoji+priorityEmoji+baseChannelName instance.newChannelName = pinEmoji+priorityEmoji+baseChannelName
+2 -2
View File
@@ -73,14 +73,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.claiming.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) if (creator && generalConfig.data.logs.logMessages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
+1 -1
View File
@@ -47,7 +47,7 @@ export async function registerActions(){
const {guild,channel,user,filter,list} = params const {guild,channel,user,filter,list} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.deleting.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:clear-logs").build(origin,{guild,channel,user,filter,list:instance.list ?? []})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:clear-logs").build(origin,{guild,channel,user,filter,list:instance.list ?? []}))
} }
+3 -3
View File
@@ -99,7 +99,7 @@ export async function registerActions(){
ticket.get("opendiscord:participants").value.forEach((participant) => { ticket.get("opendiscord:participants").value.forEach((participant) => {
//all participants that aren't roles/admins => readonly (OR non-viewable when enabled) //all participants that aren't roles/admins => readonly (OR non-viewable when enabled)
if (participant.type == "user"){ if (participant.type == "user"){
if (generalConfig.data.system.removeParticipantsOnClose) permissions.push({ if (generalConfig.data.ticketSystem.removeParticipantsOnClose) permissions.push({
type:discord.OverwriteType.Member, type:discord.OverwriteType.Member,
id:participant.id, id:participant.id,
allow:[], allow:[],
@@ -138,14 +138,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.closing.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.closing.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"close",reason,additionalData:null}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.closing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) if (creator && generalConfig.data.logs.logMessages.closing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"close",reason,additionalData:null}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
+12 -12
View File
@@ -91,15 +91,15 @@ export async function registerActions(){
//handle channel topic //handle channel topic
const channelTopics: string[] = [] const channelTopics: string[] = []
if (generalConfig.data.system.channelTopic.showOptionName) channelTopics.push(option.get("opendiscord:name").value) if (generalConfig.data.ticketSystem.channelTopic.showOptionName) channelTopics.push(option.get("opendiscord:name").value)
if (generalConfig.data.system.channelTopic.showOptionDescription) channelTopics.push(option.get("opendiscord:description").value) if (generalConfig.data.ticketSystem.channelTopic.showOptionDescription) channelTopics.push(option.get("opendiscord:description").value)
if (generalConfig.data.system.channelTopic.showOptionTopic) channelTopics.push(channelTopicText) if (generalConfig.data.ticketSystem.channelTopic.showOptionTopic) channelTopics.push(channelTopicText)
if (generalConfig.data.system.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.get("opendiscord:none").renderDisplayName()) if (generalConfig.data.ticketSystem.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.get("opendiscord:none").renderDisplayName())
if (generalConfig.data.system.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+lang.getTranslation("params.uppercase.open")) if (generalConfig.data.ticketSystem.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+lang.getTranslation("params.uppercase.open"))
if (generalConfig.data.system.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+lang.getTranslation("params.uppercase.noone")) if (generalConfig.data.ticketSystem.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+lang.getTranslation("params.uppercase.noone"))
if (generalConfig.data.system.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+lang.getTranslation("params.uppercase.no")) if (generalConfig.data.ticketSystem.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+lang.getTranslation("params.uppercase.no"))
if (generalConfig.data.system.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(user.id)) if (generalConfig.data.ticketSystem.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(user.id))
if (generalConfig.data.system.channelTopic.showParticipants) channelTopics.push("**"+lang.getTranslation("params.uppercase.participants")+":** "+participants.map((p) => (p.type == "user") ? discord.userMention(p.id) : discord.roleMention(p.id)).join(", ")) if (generalConfig.data.ticketSystem.channelTopic.showParticipants) channelTopics.push("**"+lang.getTranslation("params.uppercase.participants")+":** "+participants.map((p) => (p.type == "user") ? discord.userMention(p.id) : discord.roleMention(p.id)).join(", "))
//create channel //create channel
const channel = await guild.channels.create({ const channel = await guild.channels.create({
@@ -192,7 +192,7 @@ export async function registerActions(){
ticket.get("opendiscord:ticket-message").value = ticketMsg.id ticket.get("opendiscord:ticket-message").value = ticketMsg.id
//pin ticket message (if required) //pin ticket message (if required)
if (generalConfig.data.system.pinFirstTicketMessage && ticketMsg.pinnable) await ticketMsg.pin("Ticket Message") if (generalConfig.data.ticketSystem.pinFirstTicketMessage && ticketMsg.pinnable) await ticketMsg.pin("Ticket Message")
//manage stats //manage stats
await opendiscord.statistics.get("opendiscord:ticket").setStat("opendiscord:messages-sent",ticket.id.value,1,"increase") await opendiscord.statistics.get("opendiscord:ticket").setStat("opendiscord:messages-sent",ticket.id.value,1,"increase")
@@ -212,13 +212,13 @@ export async function registerActions(){
if (!ticket || !channel) return opendiscord.log("Ticket Creation Error: Unable to send ticket message. Previous worker failed!","error") if (!ticket || !channel) return opendiscord.log("Ticket Creation Error: Unable to send ticket message. Previous worker failed!","error")
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.creation.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.creation.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-logs").build(origin,{guild,channel,user,ticket})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-logs").build(origin,{guild,channel,user,ticket}))
} }
//to dm //to dm
if (generalConfig.data.system.messages.creation.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-dm").build(origin,{guild,channel,user,ticket})) if (generalConfig.data.logs.logMessages.creation.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-dm").build(origin,{guild,channel,user,ticket}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,answers,option} = params const {guild,user,answers,option} = params
+3 -3
View File
@@ -38,14 +38,14 @@ export async function registerActions(){
}), }),
new api.ODWorker("opendiscord:check-global-limits",2,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:check-global-limits",2,(instance,params,origin,cancel) => {
const generalConfig = opendiscord.configs.get("opendiscord:general") const generalConfig = opendiscord.configs.get("opendiscord:general")
if (!generalConfig.data.system.limits.enabled) return if (!generalConfig.data.ticketSystem.limits.enabled) return
const allTickets = opendiscord.tickets.getAll() const allTickets = opendiscord.tickets.getAll()
const globalTicketCount = allTickets.length const globalTicketCount = allTickets.length
const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.exists("opendiscord:opened-by") && (ticket.get("opendiscord:opened-by").value == params.user.id)) const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.exists("opendiscord:opened-by") && (ticket.get("opendiscord:opened-by").value == params.user.id))
const userTicketCount = userTickets.length const userTicketCount = userTickets.length
if (globalTicketCount >= generalConfig.data.system.limits.globalMaximum){ if (globalTicketCount >= generalConfig.data.ticketSystem.limits.globalMaximum){
instance.valid = false instance.valid = false
instance.reason = "global-limit" instance.reason = "global-limit"
opendiscord.log(params.user.displayName+" tried to create a ticket but reached the limit!","info",[ opendiscord.log(params.user.displayName+" tried to create a ticket but reached the limit!","info",[
@@ -55,7 +55,7 @@ export async function registerActions(){
{key:"limit",value:"global"} {key:"limit",value:"global"}
]) ])
return cancel() return cancel()
}else if (userTicketCount >= generalConfig.data.system.limits.userMaximum){ }else if (userTicketCount >= generalConfig.data.ticketSystem.limits.userMaximum){
instance.valid = false instance.valid = false
instance.reason = "global-user-limit" instance.reason = "global-user-limit"
opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[
+2 -2
View File
@@ -60,14 +60,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.deleting.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.deleting.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) if (creator && generalConfig.data.logs.logMessages.deleting.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null}))
}), }),
new api.ODWorker("opendiscord:delete-channel",1,async (instance,params,origin,cancel) => { new api.ODWorker("opendiscord:delete-channel",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
+2 -2
View File
@@ -140,14 +140,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason,data} = params const {guild,channel,user,ticket,reason,data} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.moving.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.moving.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"move",reason,additionalData:data}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.moving.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) if (creator && generalConfig.data.logs.logMessages.moving.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"move",reason,additionalData:data}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
+2 -2
View File
@@ -73,14 +73,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.pinning.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) if (creator && generalConfig.data.logs.logMessages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
+2 -2
View File
@@ -88,13 +88,13 @@ export async function registerActions(){
if (!instance.role || !instance.result) return if (!instance.role || !instance.result) return
//to logs //to logs
if (generalConfig.data.system.logs.enabled && (generalConfig.data.system.messages.reactionRole.logs)){ if (generalConfig.data.logs.enabled && (generalConfig.data.logs.logMessages.reactionRole.logs)){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-logs").build(origin,{guild,user,role:instance.role,result:instance.result})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-logs").build(origin,{guild,user,role:instance.role,result:instance.result}))
} }
//to dm //to dm
if (generalConfig.data.system.messages.reactionRole.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-dm").build(origin,{guild,user,role:instance.role,result:instance.result})) if (generalConfig.data.logs.logMessages.reactionRole.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-dm").build(origin,{guild,user,role:instance.role,result:instance.result}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,option} = params const {guild,user,option} = params
+2 -2
View File
@@ -44,14 +44,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason,data} = params const {guild,channel,user,ticket,reason,data} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.removing.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.removing.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.removing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) if (creator && generalConfig.data.logs.logMessages.removing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,data} = params const {guild,channel,user,ticket,data} = params
+2 -2
View File
@@ -52,14 +52,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason,data} = params const {guild,channel,user,ticket,reason,data} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.renaming.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.renaming.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.renaming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) if (creator && generalConfig.data.logs.logMessages.renaming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
+3 -3
View File
@@ -29,7 +29,7 @@ export async function registerActions(){
ticket.get("opendiscord:open").value = true ticket.get("opendiscord:open").value = true
ticket.get("opendiscord:busy").value = true ticket.get("opendiscord:busy").value = true
if (generalConfig.data.system.disableAutocloseAfterReopen){ if (generalConfig.data.ticketSystem.disableAutocloseAfterReopen){
//disable autoclose after reopen //disable autoclose after reopen
ticket.get("opendiscord:autoclose-enabled").value = false ticket.get("opendiscord:autoclose-enabled").value = false
ticket.get("opendiscord:autoclose-hours").value = 0 ticket.get("opendiscord:autoclose-hours").value = 0
@@ -136,14 +136,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.reopening.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.reopening.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.reopening.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) if (creator && generalConfig.data.logs.logMessages.reopening.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
+2 -2
View File
@@ -69,14 +69,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.claiming.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) if (creator && generalConfig.data.logs.logMessages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
+2 -2
View File
@@ -64,14 +64,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.pinning.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null}))
} }
//to dm //to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) if (creator && generalConfig.data.logs.logMessages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null}))
}), }),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
+9 -9
View File
@@ -29,15 +29,15 @@ export async function registerActions(){
//handle channel topic //handle channel topic
const channelTopics: string[] = [] const channelTopics: string[] = []
if (generalConfig.data.system.channelTopic.showOptionName) channelTopics.push(ticket.option.get("opendiscord:name").value) if (generalConfig.data.ticketSystem.channelTopic.showOptionName) channelTopics.push(ticket.option.get("opendiscord:name").value)
if (generalConfig.data.system.channelTopic.showOptionDescription) channelTopics.push(ticket.option.get("opendiscord:description").value) if (generalConfig.data.ticketSystem.channelTopic.showOptionDescription) channelTopics.push(ticket.option.get("opendiscord:description").value)
if (generalConfig.data.system.channelTopic.showOptionTopic) channelTopics.push(ticket.get("opendiscord:topic").value) if (generalConfig.data.ticketSystem.channelTopic.showOptionTopic) channelTopics.push(ticket.get("opendiscord:topic").value)
if (generalConfig.data.system.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).renderDisplayName()) if (generalConfig.data.ticketSystem.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).renderDisplayName())
if (generalConfig.data.system.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+(closed ? lang.getTranslation("params.uppercase.closed") : lang.getTranslation("params.uppercase.open"))) if (generalConfig.data.ticketSystem.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+(closed ? lang.getTranslation("params.uppercase.closed") : lang.getTranslation("params.uppercase.open")))
if (generalConfig.data.system.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+(claimedBy ? discord.userMention(claimedBy) : lang.getTranslation("params.uppercase.noone"))) if (generalConfig.data.ticketSystem.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+(claimedBy ? discord.userMention(claimedBy) : lang.getTranslation("params.uppercase.noone")))
if (generalConfig.data.system.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+(pinned ? lang.getTranslation("params.uppercase.yes") : lang.getTranslation("params.uppercase.no"))) if (generalConfig.data.ticketSystem.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+(pinned ? lang.getTranslation("params.uppercase.yes") : lang.getTranslation("params.uppercase.no")))
if (generalConfig.data.system.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(creator)) if (generalConfig.data.ticketSystem.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(creator))
if (generalConfig.data.system.channelTopic.showParticipants) channelTopics.push("**"+lang.getTranslation("params.uppercase.participants")+":** "+ticket.get("opendiscord:participants").value.map((p) => (p.type == "user") ? discord.userMention(p.id) : discord.roleMention(p.id)).join(", ")) if (generalConfig.data.ticketSystem.channelTopic.showParticipants) channelTopics.push("**"+lang.getTranslation("params.uppercase.participants")+":** "+ticket.get("opendiscord:participants").value.map((p) => (p.type == "user") ? discord.userMention(p.id) : discord.roleMention(p.id)).join(", "))
//update channel //update channel
channel.setTopic(channelTopics.join(" • "),"Topic Changed") channel.setTopic(channelTopics.join(" • "),"Topic Changed")
+5 -5
View File
@@ -29,7 +29,7 @@ export async function replyHasPermissions(instance:api.ODButtonResponderInstance
//check permissions //check permissions
const {user,member,channel,guild} = instance const {user,member,channel,guild} = instance
const generalConfig = opendiscord.configs.get("opendiscord:general") const generalConfig = opendiscord.configs.get("opendiscord:general")
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions[commandName],"support",user,member,channel,guild,settings) const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.permissions[commandName],"support",user,member,channel,guild,settings)
if (!permsResult.hasPerms){ if (!permsResult.hasPerms){
if (permsResult.reason == "not-in-server" && channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) if (permsResult.reason == "not-in-server" && channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
@@ -139,18 +139,18 @@ export async function replyMessageMustBeSentBeforeClose(instance:api.ODButtonRes
const {user,member,channel,guild} = instance const {user,member,channel,guild} = instance
const generalConfig = opendiscord.configs.get("opendiscord:general") const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages const lang = opendiscord.languages
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions[commandName],"support",user,member,channel,guild) const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.permissions[commandName],"support",user,member,channel,guild)
if (!permsResult.hasPerms) throw new api.ODSystemError("Please check permissions before using replyMessageMustBeSentBeforeClose()") if (!permsResult.hasPerms) throw new api.ODSystemError("Please check permissions before using replyMessageMustBeSentBeforeClose()")
if (!guild || channel.isDMBased()) throw new api.ODSystemError("replyMessageMustBeSentBeforeClose() must be used in a guild and not a DM channel.") if (!guild || channel.isDMBased()) throw new api.ODSystemError("replyMessageMustBeSentBeforeClose() must be used in a guild and not a DM channel.")
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){ if (!permsResult.isAdmin && (!generalConfig.data.ticketSystem.allowCloseBeforeMessage || !generalConfig.data.ticketSystem.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel) const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){ if (analysis && !generalConfig.data.ticketSystem.allowCloseBeforeMessage && analysis.totalMessages < 1){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")})) if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return false return false
} }
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){ if (analysis && !generalConfig.data.ticketSystem.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")})) if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return false return false
} }
+2 -2
View File
@@ -255,7 +255,7 @@ const ticketButtons = () => {
instance.setMode("button") instance.setMode("button")
instance.setCustomId("od:pin-ticket") instance.setCustomId("od:pin-ticket")
instance.setColor("gray") instance.setColor("gray")
instance.setEmoji(generalConfig.data.system.pinEmoji) instance.setEmoji(generalConfig.data.ticketSystem.pinEmoji)
instance.setLabel(lang.getTranslation("actions.buttons.pin")) instance.setLabel(lang.getTranslation("actions.buttons.pin"))
}) })
) )
@@ -269,7 +269,7 @@ const ticketButtons = () => {
instance.setMode("button") instance.setMode("button")
instance.setCustomId("od:unpin-ticket") instance.setCustomId("od:unpin-ticket")
instance.setColor("gray") instance.setColor("gray")
instance.setEmoji(generalConfig.data.system.pinEmoji) instance.setEmoji(generalConfig.data.ticketSystem.pinEmoji)
instance.setLabel(lang.getTranslation("actions.buttons.unpin")) instance.setLabel(lang.getTranslation("actions.buttons.unpin"))
}) })
) )
+53 -53
View File
@@ -42,7 +42,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin) const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",customTitle ?? lang.getTranslation("errors.titles.internalError"))) instance.setTitle(utilities.emojiTitle("❌",customTitle ?? lang.getTranslation("errors.titles.internalError")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method]) + (layout == "simple") ? "\n"+error : "") instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method]) + (layout == "simple") ? "\n"+error : "")
@@ -75,7 +75,7 @@ const errorEmbeds = () => {
}) })
const commandSyntax = "**"+error.prefix+error.name+" "+optionSyntax.join(" ")+"**" const commandSyntax = "**"+error.prefix+error.name+" "+optionSyntax.join(" ")+"**"
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.optionMissing"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.optionMissing")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.optionMissing")) instance.setDescription(lang.getTranslation("errors.descriptions.optionMissing"))
@@ -130,7 +130,7 @@ const errorEmbeds = () => {
else if (error.reason == "channel_type" && error.option.type == "channel") reasonValue = lang.getTranslation("errors.optionInvalidReasons.channelType") else if (error.reason == "channel_type" && error.option.type == "channel") reasonValue = lang.getTranslation("errors.optionInvalidReasons.channelType")
else if (error.reason == "not_in_guild") reasonValue = lang.getTranslation("errors.optionInvalidReasons.notInGuild") else if (error.reason == "not_in_guild") reasonValue = lang.getTranslation("errors.optionInvalidReasons.notInGuild")
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.optionInvalid"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.optionInvalid")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.optionInvalid")+"\n"+reasonTitle+": `"+reasonValue+"`") instance.setDescription(lang.getTranslation("errors.descriptions.optionInvalid")+"\n"+reasonTitle+": `"+reasonValue+"`")
@@ -144,7 +144,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-unknown-command",0,async (instance,params) => { new api.ODWorker("opendiscord:error-unknown-command",0,async (instance,params) => {
const {user} = params const {user} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownCommand"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownCommand")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.unknownCommand")) instance.setDescription(lang.getTranslation("errors.descriptions.unknownCommand"))
@@ -169,7 +169,7 @@ const errorEmbeds = () => {
else if (perm == "discord-administrator") return "- "+lang.getTranslation("errors.permissions.discord-administrator") else if (perm == "discord-administrator") return "- "+lang.getTranslation("errors.permissions.discord-administrator")
}).join("\n") }).join("\n")
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissions",[method])) instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissions",[method]))
@@ -185,7 +185,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin) const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsCooldown",[method])) instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsCooldown",[method]))
@@ -201,7 +201,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin) const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsBlacklist",[method])) instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsBlacklist",[method]))
@@ -214,7 +214,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,origin) => {
const {user,limit} = params const {user,limit} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
if (limit == "global") instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsLimitGlobal")) if (limit == "global") instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsLimitGlobal"))
@@ -232,7 +232,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin) const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.internalError"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.internalError")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method])) instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method]))
@@ -247,7 +247,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,origin) => {
const {user} = params const {user} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownTicket"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownTicket")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.unknownTicket")) instance.setDescription(lang.getTranslation("errors.descriptions.unknownTicket"))
@@ -261,7 +261,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,origin) => {
const {user} = params const {user} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.deprecatedTicket"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.deprecatedTicket")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.deprecatedTicket")) instance.setDescription(lang.getTranslation("errors.descriptions.deprecatedTicket"))
@@ -281,7 +281,7 @@ const errorEmbeds = () => {
}else return "- `"+option.id.value+"`" }else return "- `"+option.id.value+"`"
}).join("\n") }).join("\n")
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownOption"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownOption")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo"))
@@ -301,7 +301,7 @@ const errorEmbeds = () => {
}else return "- `"+panel.id.value+"`" }else return "- `"+panel.id.value+"`"
}).join("\n") }).join("\n")
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownPanel"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownPanel")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.addFields({name:lang.getTranslation("params.uppercase.validPanels")+":",value:renderedPanels}) instance.addFields({name:lang.getTranslation("params.uppercase.validPanels")+":",value:renderedPanels})
@@ -317,7 +317,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin) const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.notInGuild"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.notInGuild")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.notInGuild",[method])) instance.setDescription(lang.getTranslationWithParams("errors.descriptions.notInGuild",[method]))
@@ -332,7 +332,7 @@ const errorEmbeds = () => {
const method = (origin == "ticket-move" || origin == "ticket-pin" || origin == "ticket-rename" || origin == "ticket-unpin" || origin == "ticket-priority" || origin == "ticket-transfer") ? origin : getMethodFromOrigin(origin) const method = (origin == "ticket-move" || origin == "ticket-pin" || origin == "ticket-rename" || origin == "ticket-unpin" || origin == "ticket-priority" || origin == "ticket-transfer") ? origin : getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.channelRename"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.channelRename")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.channelRename")) instance.setDescription(lang.getTranslation("errors.descriptions.channelRename"))
@@ -352,7 +352,7 @@ const errorEmbeds = () => {
const method = (origin == "ticket-create" || origin == "ticket-close" || origin == "ticket-reopen" || origin == "ticket-claim" || origin == "ticket-unclaim" || origin == "ticket-move") ? origin : getMethodFromOrigin(origin) const method = (origin == "ticket-create" || origin == "ticket-close" || origin == "ticket-reopen" || origin == "ticket-claim" || origin == "ticket-unclaim" || origin == "ticket-move") ? origin : getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
//TODO TRANSLATION!!! //TODO TRANSLATION!!!
instance.setTitle(utilities.emojiTitle("❌","Unable To Change Category")) instance.setTitle(utilities.emojiTitle("❌","Unable To Change Category"))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
@@ -376,7 +376,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin) const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.busy"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.busy")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.busy",[method])) instance.setDescription(lang.getTranslationWithParams("errors.descriptions.busy",[method]))
@@ -501,7 +501,7 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-ticket-unknown",0,async (instance,params) => { new api.ODWorker("opendiscord:stats-ticket-unknown",0,async (instance,params) => {
const {user,id} = params const {user,id} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownTicket"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownTicket")))
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.statsError",[discord.channelMention(id)])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.statsError",[discord.channelMention(id)]))
@@ -534,8 +534,8 @@ const panelEmbeds = () => {
instance.setDescription(embedOptions.description) instance.setDescription(embedOptions.description)
} }
if (panel.get("opendiscord:enable-max-tickets-warning-embed").value && generalConfig.data.system.limits.enabled){ if (panel.get("opendiscord:enable-max-tickets-warning-embed").value && generalConfig.data.ticketSystem.limits.enabled){
instance.setDescription(instance.data.description+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*") instance.setDescription(instance.data.description+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.ticketSystem.limits.userMaximum.toString()])+"*")
} }
if (panel.get("opendiscord:describe-options-in-embed-fields").value){ if (panel.get("opendiscord:describe-options-in-embed-fields").value){
@@ -623,12 +623,12 @@ const ticketEmbeds = () => {
if (ticket.option.get("opendiscord:questions").value.length > 0){ if (ticket.option.get("opendiscord:questions").value.length > 0){
//show config fields if mixing is allowed //show config fields if mixing is allowed
if (generalConfig.data.system.displayFieldsWithQuestions) instance.addFields(...embedOptions.fields) if (generalConfig.data.ticketSystem.displayFieldsWithQuestions) instance.addFields(...embedOptions.fields)
const answers = ticket.get("opendiscord:answers").value const answers = ticket.get("opendiscord:answers").value
answers.forEach((answer) => { answers.forEach((answer) => {
if (!answer.value || answer.value.length == 0) return if (!answer.value || answer.value.length == 0) return
if (generalConfig.data.system.questionFieldsInCodeBlock) instance.addFields({name:answer.name,value:"```"+answer.value.slice(0,1024-6)+"```",inline:false}) if (generalConfig.data.ticketSystem.questionFieldsInCodeBlock) instance.addFields({name:answer.name,value:"```"+answer.value.slice(0,1024-6)+"```",inline:false})
else instance.addFields({name:answer.name,value:answer.value,inline:false}) else instance.addFields({name:answer.name,value:answer.value,inline:false})
}) })
}else if (embedOptions.fields){ }else if (embedOptions.fields){
@@ -656,7 +656,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close"))) instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close")))
instance.setDescription(lang.getTranslation("actions.descriptions.close")) instance.setDescription(lang.getTranslation("actions.descriptions.close"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -670,7 +670,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔓",lang.getTranslation("actions.titles.reopen"))) instance.setTitle(utilities.emojiTitle("🔓",lang.getTranslation("actions.titles.reopen")))
instance.setDescription(lang.getTranslation("actions.descriptions.reopen")) instance.setDescription(lang.getTranslation("actions.descriptions.reopen"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -684,7 +684,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🗑️",lang.getTranslation("actions.titles.delete"))) instance.setTitle(utilities.emojiTitle("🗑️",lang.getTranslation("actions.titles.delete")))
instance.setDescription(lang.getTranslation("actions.descriptions.delete")) instance.setDescription(lang.getTranslation("actions.descriptions.delete"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -698,7 +698,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👋",lang.getTranslation("actions.titles.claim"))) instance.setTitle(utilities.emojiTitle("👋",lang.getTranslation("actions.titles.claim")))
instance.setDescription(lang.getTranslation("actions.descriptions.claim")) instance.setDescription(lang.getTranslation("actions.descriptions.claim"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -712,7 +712,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim"))) instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslation("actions.descriptions.unclaim")) instance.setDescription(lang.getTranslation("actions.descriptions.unclaim"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -724,9 +724,9 @@ const ticketEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.pin"))) instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setDescription(lang.getTranslation("actions.descriptions.pin")) instance.setDescription(lang.getTranslation("actions.descriptions.pin"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -738,9 +738,9 @@ const ticketEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.unpin"))) instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setDescription(lang.getTranslation("actions.descriptions.unpin")) instance.setDescription(lang.getTranslation("actions.descriptions.unpin"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -754,7 +754,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename"))) instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.rename",["`#"+data+"`"])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.rename",["`#"+data+"`"]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -768,7 +768,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move"))) instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.move",["`"+data.get("opendiscord:name").value+"`"])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.move",["`"+data.get("opendiscord:name").value+"`"]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -782,7 +782,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add"))) instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.add",[discord.userMention(data.id)])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.add",[discord.userMention(data.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -796,7 +796,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.remove"))) instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.remove")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.remove",[discord.userMention(data.id)])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.remove",[discord.userMention(data.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -828,10 +828,10 @@ const ticketEmbeds = () => {
instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim"))) instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslation("actions.logs.unclaimDm")) instance.setDescription(lang.getTranslation("actions.logs.unclaimDm"))
}else if (mode == "pin"){ }else if (mode == "pin"){
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.pin"))) instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setDescription(lang.getTranslation("actions.logs.pinDm")) instance.setDescription(lang.getTranslation("actions.logs.pinDm"))
}else if (mode == "unpin"){ }else if (mode == "unpin"){
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.unpin"))) instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setDescription(lang.getTranslation("actions.logs.unpinDm")) instance.setDescription(lang.getTranslation("actions.logs.unpinDm"))
}else if (mode == "rename"){ }else if (mode == "rename"){
instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename"))) instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename")))
@@ -864,7 +864,7 @@ const ticketEmbeds = () => {
{name:lang.getTranslation("params.uppercase.ticket")+":",value:"```#"+(channel ? channel.name : "<unknown>")+"```",inline:false}, {name:lang.getTranslation("params.uppercase.ticket")+":",value:"```#"+(channel ? channel.name : "<unknown>")+"```",inline:false},
{name:lang.getTranslation("params.uppercase.option")+":",value:"```"+(ticket.option.get("opendiscord:name").value)+"```",inline:false}, {name:lang.getTranslation("params.uppercase.option")+":",value:"```"+(ticket.option.get("opendiscord:name").value)+"```",inline:false},
) )
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```",inline:false}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```",inline:false})
if (mode == "close"){ if (mode == "close"){
instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close"))) instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close")))
@@ -882,10 +882,10 @@ const ticketEmbeds = () => {
instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim"))) instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslationWithParams("actions.logs.unclaimLog",[discord.userMention(user.id)])) instance.setDescription(lang.getTranslationWithParams("actions.logs.unclaimLog",[discord.userMention(user.id)]))
}else if (mode == "pin"){ }else if (mode == "pin"){
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.pin"))) instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setDescription(lang.getTranslationWithParams("actions.logs.pinLog",[discord.userMention(user.id)])) instance.setDescription(lang.getTranslationWithParams("actions.logs.pinLog",[discord.userMention(user.id)]))
}else if (mode == "unpin"){ }else if (mode == "unpin"){
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.unpin"))) instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setDescription(lang.getTranslationWithParams("actions.logs.unpinLog",[discord.userMention(user.id)])) instance.setDescription(lang.getTranslationWithParams("actions.logs.unpinLog",[discord.userMention(user.id)]))
}else if (mode == "rename"){ }else if (mode == "rename"){
instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename"))) instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename")))
@@ -938,7 +938,7 @@ const blacklistEmbeds = () => {
if (blacklist){ if (blacklist){
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistGetSuccess",[discord.userMention(data.id)])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistGetSuccess",[discord.userMention(data.id)]))
if (blacklist.reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(blacklist.reason ?? "/")+"```"}) if (blacklist.reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(blacklist.reason ?? "/")+"```"})
}else instance.setDescription("*"+lang.getTranslationWithParams("actions.descriptions.blacklistGetEmpty",[discord.userMention(data.id)])+"*") }else instance.setDescription("*"+lang.getTranslationWithParams("actions.descriptions.blacklistGetEmpty",[discord.userMention(data.id)])+"*")
}) })
@@ -954,7 +954,7 @@ const blacklistEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🚫",lang.getTranslation("actions.titles.blacklistAdd"))) instance.setTitle(utilities.emojiTitle("🚫",lang.getTranslation("actions.titles.blacklistAdd")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistAdd",[discord.userMention(data.id)])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistAdd",[discord.userMention(data.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -968,7 +968,7 @@ const blacklistEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🆓",lang.getTranslation("actions.titles.blacklistRemove"))) instance.setTitle(utilities.emojiTitle("🆓",lang.getTranslation("actions.titles.blacklistRemove")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistRemove",[discord.userMention(data.id)])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistRemove",[discord.userMention(data.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -985,7 +985,7 @@ const blacklistEmbeds = () => {
instance.setTitle(utilities.emojiTitle((mode == "add") ? "🚫" : "🆓",title)) instance.setTitle(utilities.emojiTitle((mode == "add") ? "🚫" : "🆓",title))
instance.setTimestamp(new Date()) instance.setTimestamp(new Date())
instance.setDescription(text) instance.setDescription(text)
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -1004,7 +1004,7 @@ const blacklistEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setTimestamp(new Date()) instance.setTimestamp(new Date())
instance.setDescription(text) instance.setDescription(text)
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
} }
@@ -1103,12 +1103,12 @@ const transcriptEmbeds = () => {
new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,reason} = params const {guild,channel,user,ticket,compiler,reason} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("transcripts.errors.title"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("transcripts.errors.title")))
instance.setTimestamp(new Date()) instance.setTimestamp(new Date())
instance.setDescription(lang.getTranslation("transcripts.errors.error")) instance.setDescription(lang.getTranslation("transcripts.errors.error"))
instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
} }
@@ -1289,7 +1289,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseEnabled"))) instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseEnabled")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autocloseEnabled",[time.toString()])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autocloseEnabled",[time.toString()]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -1303,7 +1303,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteEnabled"))) instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteEnabled")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autodeleteEnabled",[time.toString()])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autodeleteEnabled",[time.toString()]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -1317,7 +1317,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseDisabled"))) instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseDisabled")))
instance.setDescription(lang.getTranslation("actions.descriptions.autocloseDisabled")) instance.setDescription(lang.getTranslation("actions.descriptions.autocloseDisabled"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -1331,7 +1331,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteDisabled"))) instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteDisabled")))
instance.setDescription(lang.getTranslation("actions.descriptions.autodeleteDisabled")) instance.setDescription(lang.getTranslation("actions.descriptions.autodeleteDisabled"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
} }
@@ -1361,7 +1361,7 @@ const extraEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🚨",lang.getTranslation("actions.titles.prioritySet"))) instance.setTitle(utilities.emojiTitle("🚨",lang.getTranslation("actions.titles.prioritySet")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.prioritySet",["**"+priority.renderDisplayName()+"**",discord.userMention(user.id)])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.prioritySet",["**"+priority.renderDisplayName()+"**",discord.userMention(user.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
@@ -1388,7 +1388,7 @@ const extraEmbeds = () => {
instance.setColor(generalConfig.data.mainColor) instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.transfer"))) instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.transfer")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.transfer",[discord.userMention(oldCreator.id),discord.userMention(newCreator.id),discord.userMention(user.id)])) instance.setDescription(lang.getTranslationWithParams("actions.descriptions.transfer",[discord.userMention(oldCreator.id),discord.userMention(newCreator.id),discord.userMention(user.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"}) if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
}) })
) )
} }
+16 -16
View File
@@ -286,8 +286,8 @@ const panelMessages = () => {
instance.setContent(text) instance.setContent(text)
} }
if (panel.get("opendiscord:enable-max-tickets-warning-text").value && generalConfig.data.system.limits.enabled){ if (panel.get("opendiscord:enable-max-tickets-warning-text").value && generalConfig.data.ticketSystem.limits.enabled){
instance.setContent(instance.data.content+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*") instance.setContent(instance.data.content+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.ticketSystem.limits.userMaximum.toString()])+"*")
} }
//add embed //add embed
@@ -399,7 +399,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:ticket-message-components",1,async (instance,params,origin) => { new api.ODWorker("opendiscord:ticket-message-components",1,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
//add components //add components
if (generalConfig.data.system.enableTicketClaimButtons && !ticket.get("opendiscord:closed").value){ if (generalConfig.data.ticketSystem.enableTicketClaimButtons && !ticket.get("opendiscord:closed").value){
//enable ticket claiming //enable ticket claiming
if (ticket.get("opendiscord:claimed").value){ if (ticket.get("opendiscord:claimed").value){
instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("ticket-message",{guild,channel,user,ticket})) instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -407,7 +407,7 @@ const ticketMessages = () => {
instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("ticket-message",{guild,channel,user,ticket})) instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("ticket-message",{guild,channel,user,ticket}))
} }
} }
if (generalConfig.data.system.enableTicketPinButtons && !ticket.get("opendiscord:closed").value){ if (generalConfig.data.ticketSystem.enableTicketPinButtons && !ticket.get("opendiscord:closed").value){
//enable ticket pinning //enable ticket pinning
if (ticket.get("opendiscord:pinned").value){ if (ticket.get("opendiscord:pinned").value){
instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("ticket-message",{guild,channel,user,ticket})) instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -415,7 +415,7 @@ const ticketMessages = () => {
instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("ticket-message",{guild,channel,user,ticket})) instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("ticket-message",{guild,channel,user,ticket}))
} }
} }
if (generalConfig.data.system.enableTicketCloseButtons){ if (generalConfig.data.ticketSystem.enableTicketCloseButtons){
//enable ticket closing //enable ticket closing
if (ticket.get("opendiscord:closed").value){ if (ticket.get("opendiscord:closed").value){
instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("ticket-message",{guild,channel,user,ticket})) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -424,7 +424,7 @@ const ticketMessages = () => {
} }
} }
//enable ticket deletion //enable ticket deletion
if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("ticket-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("ticket-message",{guild,channel,user,ticket}))
}), }),
new api.ODWorker("opendiscord:ticket-message-disable-components",2,async (instance,params,origin) => { new api.ODWorker("opendiscord:ticket-message-disable-components",2,async (instance,params,origin) => {
const {ticket} = params const {ticket} = params
@@ -445,8 +445,8 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:close-message",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:close-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:close-message").build(origin,{guild,channel,user,ticket,reason})) instance.addEmbed(await embeds.getSafe("opendiscord:close-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("close-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("close-message",{guild,channel,user,ticket}))
if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("close-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("close-message",{guild,channel,user,ticket}))
}) })
) )
@@ -456,8 +456,8 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:reopen-message").build(origin,{guild,channel,user,ticket,reason})) instance.addEmbed(await embeds.getSafe("opendiscord:reopen-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:close-ticket").build("reopen-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:close-ticket").build("reopen-message",{guild,channel,user,ticket}))
if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("reopen-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("reopen-message",{guild,channel,user,ticket}))
}) })
) )
@@ -476,7 +476,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:claim-message",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:claim-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:claim-message").build(origin,{guild,channel,user,ticket,reason})) instance.addEmbed(await embeds.getSafe("opendiscord:claim-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("claim-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("claim-message",{guild,channel,user,ticket}))
}) })
) )
@@ -486,7 +486,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:unclaim-message").build(origin,{guild,channel,user,ticket,reason})) instance.addEmbed(await embeds.getSafe("opendiscord:unclaim-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("unclaim-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("unclaim-message",{guild,channel,user,ticket}))
}) })
) )
@@ -496,7 +496,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:pin-message",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:pin-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:pin-message").build(origin,{guild,channel,user,ticket,reason})) instance.addEmbed(await embeds.getSafe("opendiscord:pin-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("pin-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("pin-message",{guild,channel,user,ticket}))
}) })
) )
@@ -506,7 +506,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:unpin-message").build(origin,{guild,channel,user,ticket,reason})) instance.addEmbed(await embeds.getSafe("opendiscord:unpin-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("unpin-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("unpin-message",{guild,channel,user,ticket}))
}) })
) )
@@ -732,8 +732,8 @@ const autoMessages = () => {
new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,origin) => { new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params const {guild,channel,user,ticket} = params
instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-message").build(origin,{guild,channel,user,ticket})) instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-message").build(origin,{guild,channel,user,ticket}))
if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("autoclose-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("autoclose-message",{guild,channel,user,ticket}))
if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("autoclose-message",{guild,channel,user,ticket})) if (generalConfig.data.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("autoclose-message",{guild,channel,user,ticket}))
}) })
) )
+3 -3
View File
@@ -14,7 +14,7 @@ export async function registerCommandResponders(){
const {guild,channel,user,member} = instance const {guild,channel,user,member} = instance
//check permissions //check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.blacklist,"support",user,member,channel,guild) const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.permissions.blacklist,"support",user,member,channel,guild)
if (!permsResult.hasPerms){ if (!permsResult.hasPerms){
if (permsResult.reason == "not-in-server") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) if (permsResult.reason == "not-in-server") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(origin,{guild,channel,user,permissions:["support"]})) else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(origin,{guild,channel,user,permissions:["support"]}))
@@ -83,13 +83,13 @@ export async function registerCommandResponders(){
const reason = instance.options.getString("reason",false) const reason = instance.options.getString("reason",false)
//to logs //to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.blacklisting.logs){ if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.blacklisting.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs") const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-logs").build(origin,{guild,channel,user,mode:scope,data,reason})) if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-logs").build(origin,{guild,channel,user,mode:scope,data,reason}))
} }
//to dm //to dm
if (generalConfig.data.system.messages.blacklisting.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:blacklist-dm").build(origin,{guild,channel,user,mode:scope,data,reason})) if (generalConfig.data.logs.logMessages.blacklisting.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:blacklist-dm").build(origin,{guild,channel,user,mode:scope,data,reason}))
}), }),
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => { new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand() const scope = instance.options.getSubCommand()
+1 -1
View File
@@ -90,7 +90,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType const originalMsgType = state.data.messageType
//send verifybar //send verifybar
if (generalConfig.data.system.disableVerifyBars){ if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response //verifybar disabled, directly run response
await verifybar.activate(instance,"accept") await verifybar.activate(instance,"accept")
+1 -1
View File
@@ -95,7 +95,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType const originalMsgType = state.data.messageType
//send verifybar //send verifybar
if (generalConfig.data.system.disableVerifyBars){ if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response //verifybar disabled, directly run response
await verifybar.activate(instance,"accept") await verifybar.activate(instance,"accept")
+3 -3
View File
@@ -36,7 +36,7 @@ export async function registerCommandResponders(){
//don't allow deleteWithoutTranscript to non-global-admins when enabled //don't allow deleteWithoutTranscript to non-global-admins when enabled
const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false
if (withoutTranscript && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){ if (withoutTranscript && generalConfig.data.ticketSystem.adminOnlyDeleteWithoutTranscript){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelRoleScope:false,allowChannelUserScope:false,allowGlobalRoleScope:true,allowGlobalUserScope:true}))){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelRoleScope:false,allowChannelUserScope:false,allowGlobalRoleScope:true,allowGlobalUserScope:true}))){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]}))
return cancel() return cancel()
@@ -93,7 +93,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType const originalMsgType = state.data.messageType
//send verifybar //send verifybar
if (generalConfig.data.system.disableVerifyBars){ if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response //verifybar disabled, directly run response
await verifybar.activate(instance,"accept") await verifybar.activate(instance,"accept")
@@ -146,7 +146,7 @@ export async function registerVerifyBars(){
//don't allow deleteWithoutTranscript to non-global-admins when enabled //don't allow deleteWithoutTranscript to non-global-admins when enabled
const withoutTranscript = (params.selectedButtonId == "accept-without-transcript") const withoutTranscript = (params.selectedButtonId == "accept-without-transcript")
if (withoutTranscript && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){ if (withoutTranscript && generalConfig.data.ticketSystem.adminOnlyDeleteWithoutTranscript){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelRoleScope:false,allowChannelUserScope:false,allowGlobalRoleScope:true,allowGlobalUserScope:true}))){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelRoleScope:false,allowChannelUserScope:false,allowGlobalRoleScope:true,allowGlobalUserScope:true}))){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]}))
return cancel() return cancel()
+1 -1
View File
@@ -19,7 +19,7 @@ export async function registerCommandResponders(){
//calculate slash/text mode for help menu //calculate slash/text mode for help menu
let mode: "slash"|"text" let mode: "slash"|"text"
if (generalConfig.data.slashCommands && generalConfig.data.textCommands) mode = (generalConfig.data.system.preferSlashOverText) ? "slash" : "text" if (generalConfig.data.slashCommands && generalConfig.data.textCommands) mode = (generalConfig.data.ticketSystem.preferSlashOverText) ? "slash" : "text"
else if (!generalConfig.data.slashCommands) mode = "text" else if (!generalConfig.data.slashCommands) mode = "text"
else mode = "slash" else mode = "slash"
+1 -1
View File
@@ -89,7 +89,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType const originalMsgType = state.data.messageType
//send verifybar //send verifybar
if (generalConfig.data.system.disableVerifyBars){ if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response //verifybar disabled, directly run response
await verifybar.activate(instance,"accept") await verifybar.activate(instance,"accept")
+1 -1
View File
@@ -89,7 +89,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType const originalMsgType = state.data.messageType
//send verifybar //send verifybar
if (generalConfig.data.system.disableVerifyBars){ if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response //verifybar disabled, directly run response
await verifybar.activate(instance,"accept") await verifybar.activate(instance,"accept")
+1 -1
View File
@@ -34,7 +34,7 @@ export async function registerButtonResponders(){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"})) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"}))
return cancel() return cancel()
} }
if (generalConfig.data.system.replyOnReactionRole) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result})) if (generalConfig.data.ticketSystem.replyOnReactionRole) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result}))
}) })
) )
} }
+6 -6
View File
@@ -105,7 +105,7 @@ export async function registerButtonResponders(){
if (!(await checkTicketCreationPerms(instance,"panel-button",guild,user,option))) return cancel() if (!(await checkTicketCreationPerms(instance,"panel-button",guild,user,option))) return cancel()
//CREATE TICKET //CREATE TICKET
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true) await instance.defer((generalConfig.data.ticketSystem.replyOnTicketCreation) ? "reply" : "update",true)
const res = await opendiscord.actions.get("opendiscord:create-ticket").run("panel-button",{guild,user,answers:[],option}) const res = await opendiscord.actions.get("opendiscord:create-ticket").run("panel-button",{guild,user,answers:[],option})
if (!res.channel || !res.ticket){ if (!res.channel || !res.ticket){
@@ -113,7 +113,7 @@ export async function registerButtonResponders(){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"}))
return cancel() return cancel()
} }
if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket})) if (generalConfig.data.ticketSystem.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket}))
} }
}) })
) )
@@ -147,7 +147,7 @@ export async function registerDropdownResponders(){
if (!(await checkTicketCreationPerms(instance,"panel-dropdown",guild,user,option))) return cancel() if (!(await checkTicketCreationPerms(instance,"panel-dropdown",guild,user,option))) return cancel()
//CREATE TICKET //CREATE TICKET
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true) await instance.defer((generalConfig.data.ticketSystem.replyOnTicketCreation) ? "reply" : "update",true)
const res = await opendiscord.actions.get("opendiscord:create-ticket").run("panel-dropdown",{guild,user,answers:[],option}) const res = await opendiscord.actions.get("opendiscord:create-ticket").run("panel-dropdown",{guild,user,answers:[],option})
if (!res.channel || !res.ticket){ if (!res.channel || !res.ticket){
@@ -155,7 +155,7 @@ export async function registerDropdownResponders(){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"}))
return cancel() return cancel()
} }
if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket})) if (generalConfig.data.ticketSystem.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket}))
} }
//update panel after dropdown usage (reset panel choice) //update panel after dropdown usage (reset panel choice)
@@ -214,7 +214,7 @@ export async function registerModalResponders(){
} }
}) })
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true) await instance.defer((generalConfig.data.ticketSystem.replyOnTicketCreation) ? "reply" : "update",true)
//CREATE TICKET //CREATE TICKET
const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalOrigin,{guild,user,answers,option}) const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalOrigin,{guild,user,answers,option})
@@ -223,7 +223,7 @@ export async function registerModalResponders(){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"})) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"}))
return cancel() return cancel()
} }
if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(originalOrigin,{guild,channel:res.channel,user,ticket:res.ticket})) if (generalConfig.data.ticketSystem.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(originalOrigin,{guild,channel:res.channel,user,ticket:res.ticket}))
}) })
]) ])
} }
+1 -1
View File
@@ -89,7 +89,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType const originalMsgType = state.data.messageType
//send verifybar //send verifybar
if (generalConfig.data.system.disableVerifyBars){ if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response //verifybar disabled, directly run response
await verifybar.activate(instance,"accept") await verifybar.activate(instance,"accept")
+1 -1
View File
@@ -89,7 +89,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType const originalMsgType = state.data.messageType
//send verifybar //send verifybar
if (generalConfig.data.system.disableVerifyBars){ if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response //verifybar disabled, directly run response
await verifybar.activate(instance,"accept") await verifybar.activate(instance,"accept")
+8 -8
View File
@@ -42,7 +42,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or close with reason //cancel, accept or close with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel) await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.close")) await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.close"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️") if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
})) }))
//REOPEN TICKET VERIFYBAR //REOPEN TICKET VERIFYBAR
@@ -57,7 +57,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or reopen with reason //cancel, accept or reopen with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel) await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.reopen")) await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.reopen"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️") if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
})) }))
//DELETE TICKET VERIFYBAR //DELETE TICKET VERIFYBAR
@@ -72,8 +72,8 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or delete with reason or without transcript //cancel, accept or delete with reason or without transcript
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel) await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.delete")) await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.delete"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️") if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.system.enableDeleteWithoutTranscript) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithoutTranscript,lang.getTranslation("actions.buttons.withoutTranscript"),"red","📄") if (generalConfig.data.ticketSystem.enableDeleteWithoutTranscript) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithoutTranscript,lang.getTranslation("actions.buttons.withoutTranscript"),"red","📄")
})) }))
//CLAIM TICKET VERIFYBAR //CLAIM TICKET VERIFYBAR
@@ -88,7 +88,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or claim with reason //cancel, accept or claim with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel) await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.claim")) await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.claim"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️") if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
})) }))
//UNCLAIM TICKET VERIFYBAR //UNCLAIM TICKET VERIFYBAR
@@ -103,7 +103,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or unclaim with reason //cancel, accept or unclaim with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel) await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.unclaim")) await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.unclaim"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️") if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
})) }))
//PIN TICKET VERIFYBAR //PIN TICKET VERIFYBAR
@@ -118,7 +118,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or pin with reason //cancel, accept or pin with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel) await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.pin")) await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.pin"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️") if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
})) }))
//UNPIN TICKET VERIFYBAR //UNPIN TICKET VERIFYBAR
@@ -133,6 +133,6 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or unpin with reason //cancel, accept or unpin with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel) await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.unpin")) await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.unpin"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️") if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
})) }))
} }
-3
View File
@@ -32,9 +32,6 @@ export interface ODTicketOptionIdMappings extends ODOptionIdConstraint {
"opendiscord:channel-prefix":ODOptionData<string>, "opendiscord:channel-prefix":ODOptionData<string>,
"opendiscord:channel-suffix":ODOptionData<"user-name"|"user-nickname"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed">, "opendiscord:channel-suffix":ODOptionData<"user-name"|"user-nickname"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed">,
"opendiscord:channel-category":ODOptionData<string>, "opendiscord:channel-category":ODOptionData<string>,
"opendiscord:channel-category-closed":ODOptionData<string>,
"opendiscord:channel-category-backup":ODOptionData<string>,
"opendiscord:channel-categories-claimed":ODOptionData<{user:string,category:string}[]>,
"opendiscord:channel-topic":ODOptionData<string>, "opendiscord:channel-topic":ODOptionData<string>,
"opendiscord:dm-message-enabled":ODOptionData<boolean>, "opendiscord:dm-message-enabled":ODOptionData<boolean>,
+123 -64
View File
@@ -31,7 +31,7 @@ interface ODQuickSetupVariables {
globalUserLimit?:number|null, globalUserLimit?:number|null,
removeParticipantsOnClose?:boolean, removeParticipantsOnClose?:boolean,
ticketMessageLayout?:"embed"|"text"|null, ticketMessageLayout?:"embed"|"text"|null,
emojiStyle?:api.ODGeneralJsonConfig_System["emojiStyle"], emojiStyle?:api.ODGeneralJsonConfig_TicketSystem["emojiStyle"],
panelName?:string, panelName?:string,
panelDescription?:string, panelDescription?:string,
panelDropdown?:boolean, panelDropdown?:boolean,
@@ -234,7 +234,7 @@ async function renderQuickSetupBotToken(backFn:() => api.ODPromiseVoid){
cli.renderHeader(headerOpts,"⏱️ Open Ticket Quick Setup: Bot Token") cli.renderHeader(headerOpts,"⏱️ Open Ticket Quick Setup: Bot Token")
terminal.bold.blue(stepCount(2)+"Please insert the token of your discord bot.\n") terminal.bold.blue(stepCount(2)+"Please insert the token of your discord bot.\n")
terminal.gray("This is used to configure the bot and is then stored securely in the './config/general.json' file.\n\n> ") terminal.gray("This is used to configure the bot and is then stored securely in the './config/general.jsonc' file.\n\n> ")
const answer = await terminal.inputField({ const answer = await terminal.inputField({
style:terminal.white, style:terminal.white,
@@ -1203,11 +1203,7 @@ async function saveQuickSetupConfig(){
//GENERAL CONFIG //GENERAL CONFIG
const generalConfig = opendiscord.configs.get("opendiscord:general") const generalConfig = opendiscord.configs.get("opendiscord:general")
const generalConfigData: api.ODGeneralJsonConfig_GeneralData = { const generalConfigData: api.ODGeneralJsonConfig_GeneralData = {
_INFO:{ _CONFIG_VERSION:"open-ticket-"+opendiscord.versions.get("opendiscord:version").toString(),
support:"https://otdocs.dj-dj.be",
discord:"https://discord.dj-dj.be",
version:"open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()
},
token:quickSetupStorage.client?.token ?? "<unknown-token>", token:quickSetupStorage.client?.token ?? "<unknown-token>",
tokenFromENV:false, tokenFromENV:false,
@@ -1222,8 +1218,29 @@ async function saveQuickSetupConfig(){
textCommands:quickSetupStorage.textCommands ?? false, textCommands:quickSetupStorage.textCommands ?? false,
status:quickSetupStorage.status ?? {enabled:false,mode:"online",type:"custom",text:"",state:""}, status:quickSetupStorage.status ?? {enabled:false,mode:"online",type:"custom",text:"",state:""},
logs:{
enabled:(typeof quickSetupStorage.logChannel == "string"),
channel:quickSetupStorage.logChannel ?? "",
logMessages:{
creation:{dm:true,logs:true},
closing:{dm:true,logs:true},
deleting:{dm:true,logs:true},
reopening:{dm:false,logs:true},
claiming:{dm:false,logs:true},
pinning:{dm:false,logs:true},
adding:{dm:false,logs:true},
removing:{dm:false,logs:true},
renaming:{dm:false,logs:true},
moving:{dm:true,logs:true},
blacklisting:{dm:true,logs:true},
transferring:{dm:true,logs:true},
topicChange:{dm:false,logs:true},
priorityChange:{dm:false,logs:true},
reactionRole:{dm:false,logs:true}
}
},
system:{ ticketSystem:{
preferSlashOverText:quickSetupStorage.slashCommands ?? false, preferSlashOverText:quickSetupStorage.slashCommands ?? false,
sendErrorOnUnknownCommand:true, sendErrorOnUnknownCommand:true,
questionFieldsInCodeBlock:true, questionFieldsInCodeBlock:true,
@@ -1234,10 +1251,11 @@ async function saveQuickSetupConfig(){
alwaysShowReason:false, alwaysShowReason:false,
emojiStyle:quickSetupStorage.emojiStyle ?? "before", emojiStyle:quickSetupStorage.emojiStyle ?? "before",
pinEmoji:"📌", pinEmoji:"📌",
closeEmoji:"🔒",
replyOnTicketCreation:false, replyOnTicketCreation:true,
replyOnReactionRole:true, replyOnReactionRole:true,
askPriorityOnTicketCreation:false, askPriorityOnTicketCreation:true,
removeParticipantsOnClose:quickSetupStorage.removeParticipantsOnClose ?? false, removeParticipantsOnClose:quickSetupStorage.removeParticipantsOnClose ?? false,
disableAutocloseAfterReopen:true, disableAutocloseAfterReopen:true,
autodeleteRequiresClosedTicket:true, autodeleteRequiresClosedTicket:true,
@@ -1245,7 +1263,7 @@ async function saveQuickSetupConfig(){
allowCloseBeforeMessage:false, allowCloseBeforeMessage:false,
allowCloseBeforeAdminMessage:true, allowCloseBeforeAdminMessage:true,
useTranslatedConfigChecker:true, useTranslatedConfigChecker:true,
pinFirstTicketMessage:false, pinFirstTicketMessage:true,
enableTicketClaimButtons:true, enableTicketClaimButtons:true,
enableTicketCloseButtons:true, enableTicketCloseButtons:true,
@@ -1253,11 +1271,7 @@ async function saveQuickSetupConfig(){
enableTicketDeleteButtons:true, enableTicketDeleteButtons:true,
enableTicketActionWithReason:true, enableTicketActionWithReason:true,
enableDeleteWithoutTranscript:true, enableDeleteWithoutTranscript:true,
enableCreateTicketForOtherUser:true,
logs:{
enabled:(typeof quickSetupStorage.logChannel == "string"),
channel:quickSetupStorage.logChannel ?? ""
},
limits:{ limits:{
enabled:(typeof quickSetupStorage.globalUserLimit == "number"), enabled:(typeof quickSetupStorage.globalUserLimit == "number"),
@@ -1277,48 +1291,40 @@ async function saveQuickSetupConfig(){
showParticipants:false showParticipants:false
}, },
permissions:{ closedCategory:{
help:"everyone", enabled:false,
panel:"admin", categoryId:""
ticket:"everyone",
close:"admin",
delete:"admin",
reopen:"admin",
claim:"admin",
unclaim:"admin",
pin:"admin",
unpin:"admin",
move:"admin",
rename:"admin",
add:"admin",
remove:"admin",
blacklist:"admin",
stats:"everyone",
clear:"admin",
autoclose:"admin",
autodelete:"admin",
transfer:"admin",
topic:"admin",
priority:"admin",
}, },
backupCategory:{
messages:{ enabled:false,
creation:{dm:true,logs:true}, categoryId:""
closing:{dm:true,logs:true}, },
deleting:{dm:true,logs:true}, claimedCategories:[],
reopening:{dm:false,logs:true}, },
claiming:{dm:false,logs:true}, permissions:{
pinning:{dm:false,logs:true}, help:"everyone",
adding:{dm:false,logs:true}, panel:"admin",
removing:{dm:false,logs:true}, ticket:"everyone",
renaming:{dm:false,logs:true}, close:"admin",
moving:{dm:true,logs:true}, delete:"admin",
blacklisting:{dm:true,logs:true}, reopen:"admin",
transferring:{dm:true,logs:true}, claim:"admin",
topicChange:{dm:false,logs:true}, unclaim:"admin",
priorityChange:{dm:false,logs:true}, pin:"admin",
reactionRole:{dm:false,logs:true} unpin:"admin",
} move:"admin",
rename:"admin",
add:"admin",
remove:"admin",
blacklist:"admin",
stats:"everyone",
clear:"admin",
autoclose:"admin",
autodelete:"admin",
transfer:"admin",
topic:"admin",
priority:"admin",
transcripts:"admin"
} }
} }
generalConfig.data = generalConfigData generalConfig.data = generalConfigData
@@ -1330,10 +1336,11 @@ async function saveQuickSetupConfig(){
{ {
id:"example-question-1", id:"example-question-1",
name:"Example Question 1", name:"Example Question 1",
description:"This is a short text input question.",
type:"short", type:"short",
required:true, required:true,
placeholder:"Insert your short answer here!",
placeholder:"Insert answer...",
length:{ length:{
enabled:false, enabled:false,
min:0, min:0,
@@ -1343,15 +1350,69 @@ async function saveQuickSetupConfig(){
{ {
id:"example-question-2", id:"example-question-2",
name:"Example Question 2", name:"Example Question 2",
description:"This is a paragraph text input question.",
type:"paragraph", type:"paragraph",
required:false, required:false,
placeholder:"Insert your long answer here!",
placeholder:"Insert answer...",
length:{ length:{
enabled:false, enabled:false,
min:0, min:0,
max:1000 max:1000
} }
},
{
id:"example-question-3",
name:"Example Question 3",
description:"This is a dropdown question.",
type:"dropdown",
required:false,
placeholder:"Choose your answer...",
choices:[
{title:"Choice A",description:"Apple",emoji:"🍎"},
{title:"Choice B",description:"Banana",emoji:"🍌"},
{title:"Choice C",description:"Orange",emoji:"🍊"},
{title:"Choice D",description:"Kiwi",emoji:"🥝"}
]
},
{
id:"example-question-4",
name:"Example Question 4",
description:"This is a radio select question.",
type:"radio-select",
required:true,
choices:[
{title:"Choice A",description:"Up",selectedByDefault:false},
{title:"Choice B",description:"Down",selectedByDefault:false},
{title:"Choice C",description:"Left",selectedByDefault:false},
{title:"Choice D",description:"Right",selectedByDefault:false}
]
},
{
id:"example-question-5",
name:"Example Question 5",
description:"This is a checkbox select question.",
type:"checkbox-select",
required:true,
limits:{
enabled:false,
min:0,
max:10
},
choices:[
{title:"Choice A",description:"Happiness",selectedByDefault:false},
{title:"Choice B",description:"Anger",selectedByDefault:false},
{title:"Choice C",description:"Sadness",selectedByDefault:false},
{title:"Choice D",description:"Fear",selectedByDefault:false}
]
},
{
id:"example-text-display",
type:"text-display",
textContents:"This is a text display. It isn't a question, but allows you to display a text, explaination or details."
} }
] ]
questionsConfig.data = questionsConfigData questionsConfig.data = questionsConfigData
@@ -1384,9 +1445,6 @@ async function saveQuickSetupConfig(){
prefix:ticket.channelPrefix, prefix:ticket.channelPrefix,
suffix:ticket.channelSuffix, suffix:ticket.channelSuffix,
category:quickSetupStorage.ticketCategory ?? "", category:quickSetupStorage.ticketCategory ?? "",
closedCategory:"",
backupCategory:"",
claimedCategory:[],
topic:ticket.description topic:ticket.description
}, },
@@ -1482,6 +1540,7 @@ async function saveQuickSetupConfig(){
}, },
settings:{ settings:{
dropdownPlaceholder:"Open a ticket", dropdownPlaceholder:"Open a ticket",
maximumButtonsPerRow:5,
enableMaxTicketsWarningInText:(quickSetupStorage.panelLayout == "text" && (quickSetupStorage.panelMaxTicketsWarning ?? false)), enableMaxTicketsWarningInText:(quickSetupStorage.panelLayout == "text" && (quickSetupStorage.panelMaxTicketsWarning ?? false)),
enableMaxTicketsWarningInEmbed:(quickSetupStorage.panelLayout == "embed" && (quickSetupStorage.panelMaxTicketsWarning ?? false)), enableMaxTicketsWarningInEmbed:(quickSetupStorage.panelLayout == "embed" && (quickSetupStorage.panelMaxTicketsWarning ?? false)),
+2 -2
View File
@@ -58,7 +58,7 @@ export class ODOpenTicketMain extends api.ODMain {
priorities: api.ODMappedPriorityManager priorities: api.ODMappedPriorityManager
constructor(){ constructor(){
const version = api.ODVersion.fromString("opendiscord:version","v4.1.3") const version = api.ODVersion.fromString("opendiscord:version","v4.2.0")
const debugfile = new api.ODDebugFileManager("./","otdebug.txt",5000,version) const debugfile = new api.ODDebugFileManager("./","otdebug.txt",5000,version)
const console = new api.ODConsoleManager(100,debugfile) const console = new api.ODConsoleManager(100,debugfile)
const debug = new api.ODDebugger(console) const debug = new api.ODDebugger(console)
@@ -108,7 +108,7 @@ export class ODOpenTicketMain extends api.ODMain {
},"openticket") },"openticket")
this.livestatus.useMain(this) this.livestatus.useMain(this)
this.versions.add(api.ODVersion.fromString("opendiscord:version","v4.1.3")) this.versions.add(api.ODVersion.fromString("opendiscord:version","v4.2.0"))
this.versions.add(api.ODVersion.fromString("opendiscord:transcripts","v2.1.0")) this.versions.add(api.ODVersion.fromString("opendiscord:transcripts","v2.1.0"))
//OPEN TICKET //OPEN TICKET
+195 -94
View File
@@ -10,20 +10,20 @@ import { ODRoleUpdateMode } from "../api/role.js"
* It's used to generate typescript declarations for this class. * It's used to generate typescript declarations for this class.
*/ */
export interface ODConfigManagerIdMappings extends api.ODConfigManagerIdConstraint { export interface ODConfigManagerIdMappings extends api.ODConfigManagerIdConstraint {
"opendiscord:general":ODGeneralJsonConfig, "opendiscord:general":ODGeneralJsonCommentsConfig,
"opendiscord:questions":ODQuestionsJsonConfig, "opendiscord:questions":ODQuestionsJsonCommentsConfig,
"opendiscord:options":ODOptionsJsonConfig, "opendiscord:options":ODOptionsJsonCommentsConfig,
"opendiscord:panels":ODPanelsJsonConfig, "opendiscord:panels":ODPanelsJsonCommentsConfig,
"opendiscord:transcripts":ODTranscriptsJsonConfig "opendiscord:transcripts":ODTranscriptsJsonCommentsConfig
} }
/////////////////////////////////////// ///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES // CONFIG STRUCTURES, VALUES & TYPES
// --> general.json // --> general.jsonc
/////////////////////////////////////// ///////////////////////////////////////
/**## ODGeneralJsonConfig_Status `interface` /**## ODGeneralJsonConfig_Status `interface`
* This interface is an object which has all properties for the status object in the `general.json` config! * This interface is an object which has all properties for the status object in the `general.jsonc` config!
*/ */
export interface ODGeneralJsonConfig_Status { export interface ODGeneralJsonConfig_Status {
/**Is the status enabled? */ /**Is the status enabled? */
@@ -39,7 +39,7 @@ export interface ODGeneralJsonConfig_Status {
} }
/**## ODGeneralJsonConfig_MessageSettings `interface` /**## ODGeneralJsonConfig_MessageSettings `interface`
* This interface is an object which has all properties for the "system"."messages".... object in the `general.json` config! * This interface is an object which has all properties for the "system"."messages".... object in the `general.jsonc` config!
*/ */
export interface ODGeneralJsonConfig_MessageSettings { export interface ODGeneralJsonConfig_MessageSettings {
/**Enable sending DM logs to the ticket creator for this action. */ /**Enable sending DM logs to the ticket creator for this action. */
@@ -49,22 +49,10 @@ export interface ODGeneralJsonConfig_MessageSettings {
} }
/**## ODGeneralJsonConfig_CmdPermissionSettingsType `type` /**## ODGeneralJsonConfig_CmdPermissionSettingsType `type`
* This type is a collection of command permission settings for the "system"."permissions".... object in the `general.json` config! * This type is a collection of command permission settings for the "system"."permissions".... object in the `general.jsonc` config!
*/ */
export type ODGeneralJsonConfig_CmdPermissionSettingsType = "admin"|"everyone"|"none"|string export type ODGeneralJsonConfig_CmdPermissionSettingsType = "admin"|"everyone"|"none"|string
/**## ODGeneralJsonConfig_Info `interface`
* This object contains a few URLs and metadata for the config.
*/
export interface ODGeneralJsonConfig_Info {
/**A link to the Open Ticket documentation. */
support:string,
/**A link to the DJdj Development discord server. */
discord:string,
/**The version of Open Ticket this config is compatible with. */
version:string
}
/**## ODGeneralJsonConfig_SystemLogs `interface` /**## ODGeneralJsonConfig_SystemLogs `interface`
* All settings related to the log channel. * All settings related to the log channel.
*/ */
@@ -72,7 +60,9 @@ export interface ODGeneralJsonConfig_SystemLogs {
/**Enable logging. Individual actions should still be added via the `"system"."messages"..."logs"` */ /**Enable logging. Individual actions should still be added via the `"system"."messages"..."logs"` */
enabled:boolean, enabled:boolean,
/**The channel to send logs to. */ /**The channel to send logs to. */
channel:string channel:string,
/**Configure dm & log messages for all Open Ticket commands & actions. */
logMessages:ODGeneralJsonConfig_LogMessages
} }
/**## ODGeneralJsonConfig_SystemLimits `interface` /**## ODGeneralJsonConfig_SystemLimits `interface`
@@ -137,12 +127,13 @@ export interface ODGeneralJsonConfig_SystemPermissions {
transfer:ODGeneralJsonConfig_CmdPermissionSettingsType, transfer:ODGeneralJsonConfig_CmdPermissionSettingsType,
topic:ODGeneralJsonConfig_CmdPermissionSettingsType, topic:ODGeneralJsonConfig_CmdPermissionSettingsType,
priority:ODGeneralJsonConfig_CmdPermissionSettingsType, priority:ODGeneralJsonConfig_CmdPermissionSettingsType,
transcripts:ODGeneralJsonConfig_CmdPermissionSettingsType,
} }
/**## ODGeneralJsonConfig_SystemMessages `interface` /**## ODGeneralJsonConfig_LogMessages `interface`
* Configure dm & log messages for all Open Ticket commands & actions. * Configure dm & log messages for all Open Ticket commands & actions.
*/ */
export interface ODGeneralJsonConfig_SystemMessages { export interface ODGeneralJsonConfig_LogMessages {
creation:ODGeneralJsonConfig_MessageSettings, creation:ODGeneralJsonConfig_MessageSettings,
closing:ODGeneralJsonConfig_MessageSettings, closing:ODGeneralJsonConfig_MessageSettings,
deleting:ODGeneralJsonConfig_MessageSettings, deleting:ODGeneralJsonConfig_MessageSettings,
@@ -160,10 +151,10 @@ export interface ODGeneralJsonConfig_SystemMessages {
reactionRole:ODGeneralJsonConfig_MessageSettings, reactionRole:ODGeneralJsonConfig_MessageSettings,
} }
/**## ODGeneralJsonConfig_System `interface` /**## ODGeneralJsonConfig_TicketSystem `interface`
* All settings related to the ticket system. * All settings related to the ticket system.
*/ */
export interface ODGeneralJsonConfig_System { export interface ODGeneralJsonConfig_TicketSystem {
/**Prefer slash-commands over text-commands when displaying them in menu's and messages. */ /**Prefer slash-commands over text-commands when displaying them in menu's and messages. */
preferSlashOverText:boolean, preferSlashOverText:boolean,
/**Reply with "unknown command" when the prefix is used without a valid command. */ /**Reply with "unknown command" when the prefix is used without a valid command. */
@@ -184,6 +175,8 @@ export interface ODGeneralJsonConfig_System {
emojiStyle:"before"|"after"|"double"|"disabled", emojiStyle:"before"|"after"|"double"|"disabled",
/**The emoji used when pinning tickets. This is '📌' by default. */ /**The emoji used when pinning tickets. This is '📌' by default. */
pinEmoji:string, pinEmoji:string,
/**The emoji used when closing tickets. This is '🔒' by default. */
closeEmoji:string,
/**Reply with an ephemeral message when a ticket is created. */ /**Reply with an ephemeral message when a ticket is created. */
replyOnTicketCreation:boolean, replyOnTicketCreation:boolean,
@@ -220,9 +213,8 @@ export interface ODGeneralJsonConfig_System {
enableTicketActionWithReason:boolean, enableTicketActionWithReason:boolean,
/**Enable/disable the delete without transcript feature (button & /delete command). */ /**Enable/disable the delete without transcript feature (button & /delete command). */
enableDeleteWithoutTranscript:boolean, enableDeleteWithoutTranscript:boolean,
/**Enable/disable creating tickets for other users with /ticket <user>. (ADMIN ONLY) */
/**All settings related to the log channel. */ enableCreateTicketForOtherUser:boolean,
logs:ODGeneralJsonConfig_SystemLogs,
/**All settings related to global ticket limits. */ /**All settings related to global ticket limits. */
limits:ODGeneralJsonConfig_SystemLimits, limits:ODGeneralJsonConfig_SystemLimits,
@@ -230,19 +222,31 @@ export interface ODGeneralJsonConfig_System {
/**All global channel topic settings. */ /**All global channel topic settings. */
channelTopic:ODGeneralJsonConfig_SystemChannelTopic, channelTopic:ODGeneralJsonConfig_SystemChannelTopic,
/**Configure permissions for all Open Ticket commands & actions. */ /**Move closed tickets to this channel category. */
permissions:ODGeneralJsonConfig_SystemPermissions, closedCategory:{
enabled:boolean
/**Configure dm & log messages for all Open Ticket commands & actions. */ categoryId:string
messages:ODGeneralJsonConfig_SystemMessages },
/**Create tickets in this channel category when the original category is full (max 50 channels). */
backupCategory:{
enabled:boolean
categoryId:string
},
/**Move claimed tickets to the matching channel category of the user that claimed the ticket. */
claimedCategories:{
/**The user who claimed the ticket. */
user:string,
/**The category to move the ticket to. */
category:string
}[],
} }
/**## ODGeneralJsonConfig_GeneralData `interface` /**## ODGeneralJsonConfig_GeneralData `interface`
* All contents of the `general.json` config file. * All contents of the `general.jsonc` config file.
*/ */
export interface ODGeneralJsonConfig_GeneralData { export interface ODGeneralJsonConfig_GeneralData {
/**This object contains a few URLs and metadata for the config. */ /**This object contains a few URLs and metadata for the config. */
_INFO:ODGeneralJsonConfig_Info, _CONFIG_VERSION:string,
/**The token of the bot. (Empty when using `tokenFromENV`) */ /**The token of the bot. (Empty when using `tokenFromENV`) */
token:string, token:string,
@@ -269,16 +273,22 @@ export interface ODGeneralJsonConfig_GeneralData {
status:ODGeneralJsonConfig_Status, status:ODGeneralJsonConfig_Status,
/**All settings related to the ticket system. */ /**All settings related to the ticket system. */
system:ODGeneralJsonConfig_System ticketSystem:ODGeneralJsonConfig_TicketSystem,
/**Configure permissions for all Open Ticket commands & actions. */
permissions:ODGeneralJsonConfig_SystemPermissions,
/**All settings related to the log channel. */
logs:ODGeneralJsonConfig_SystemLogs,
} }
/////////////////////////////////////// ///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES // CONFIG STRUCTURES, VALUES & TYPES
// --> options.json // --> options.jsonc
/////////////////////////////////////// ///////////////////////////////////////
/**## ODOptionsJsonConfig_BaseOption `interface` /**## ODOptionsJsonConfig_BaseOption `interface`
* This interface is an object which has all basic properties for options in the `options.json` config! * The basic properties for options in the `options.jsonc` config!
*/ */
export interface ODOptionsJsonConfig_BaseOption { export interface ODOptionsJsonConfig_BaseOption {
/**The id of this option. */ /**The id of this option. */
@@ -288,7 +298,7 @@ export interface ODOptionsJsonConfig_BaseOption {
/**The description of this option. */ /**The description of this option. */
description:string, description:string,
/**The type of this option. This type also determines the other option-specific variables. */ /**The type of this option. This type also determines the other option-specific variables. */
type:"ticket"|"website"|"role", type:"ticket"|"website"|"role"|"sub-panel",
/**All settings related to the button for the 3 option types. */ /**All settings related to the button for the 3 option types. */
button:{ button:{
/**The emoji of the button. (can also be empty) */ /**The emoji of the button. (can also be empty) */
@@ -299,7 +309,7 @@ export interface ODOptionsJsonConfig_BaseOption {
} }
/**## ODOptionsJsonConfig_OptionButtonSettings `interface` /**## ODOptionsJsonConfig_OptionButtonSettings `interface`
* This interface is an object which has all button settings for ticket & reaction role options in the `options.json` config! * The button settings for ticket, sub-panel & reaction role options in the `options.jsonc` config!
*/ */
export interface ODOptionsJsonConfig_OptionButtonSettings { export interface ODOptionsJsonConfig_OptionButtonSettings {
/**The emoji of the button. (can also be empty) */ /**The emoji of the button. (can also be empty) */
@@ -311,7 +321,7 @@ export interface ODOptionsJsonConfig_OptionButtonSettings {
} }
/**## ODOptionsJsonConfig_TicketOptionEmbedSettings `interface` /**## ODOptionsJsonConfig_TicketOptionEmbedSettings `interface`
* This interface is an object which has all message embed settings for ticket options in the `options.json` config! * The message embed settings for ticket options in the `options.jsonc` config!
*/ */
export interface ODOptionsJsonConfig_TicketOptionEmbedSettings { export interface ODOptionsJsonConfig_TicketOptionEmbedSettings {
/**Is this embed enabled? */ /**Is this embed enabled? */
@@ -340,7 +350,7 @@ export interface ODOptionsJsonConfig_TicketOptionEmbedSettings {
} }
/**## ODOptionsJsonConfig_TicketOptionPingSettings `interface` /**## ODOptionsJsonConfig_TicketOptionPingSettings `interface`
* This interface is an object which has all message ping settings for ticket options in the `options.json` config! * The message ping settings for ticket options in the `options.jsonc` config!
*/ */
export interface ODOptionsJsonConfig_TicketOptionPingSettings { export interface ODOptionsJsonConfig_TicketOptionPingSettings {
/**Ping `@here`. */ /**Ping `@here`. */
@@ -361,23 +371,12 @@ export interface ODOptionsJsonConfig_TicketOptionChannelSettings {
suffix:"user-name"|"user-nickname"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed", suffix:"user-name"|"user-nickname"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed",
/**An optional discord category id to create this ticket in. */ /**An optional discord category id to create this ticket in. */
category:string, category:string,
/**An optional discord category id to move this ticket to when closed. */
closedCategory:string,
/**An optional discord category id to create this ticket in when the primary one is full (max. 50 tickets). */
backupCategory:string,
/**A list of discord category ids to move this ticket to when claimed by a specific user. */
claimedCategory:{
/**The user which claimed the ticket. */
user:string,
/**The category to move the ticket to when claimed by this user. */
category:string
}[],
/**The channel topic shown at the top of the channel in discord. */ /**The channel topic shown at the top of the channel in discord. */
topic:string topic:string
} }
/**## ODOptionsJsonConfig_TicketOption `interface` /**## ODOptionsJsonConfig_TicketOption `interface`
* This interface is an object which has all ticket properties for options in the `options.json` config! * All properties for ticket options in the `options.jsonc` config!
*/ */
export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_BaseOption { export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_BaseOption {
type:"ticket", type:"ticket",
@@ -388,7 +387,7 @@ export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_Ba
readonlyAdmins:string[], readonlyAdmins:string[],
/**When enabled, blacklisted users can still create this ticket type. (used for appeals, etc) */ /**When enabled, blacklisted users can still create this ticket type. (used for appeals, etc) */
allowCreationByBlacklistedUsers:boolean, allowCreationByBlacklistedUsers:boolean,
/**A list of valid question ids from the `questions.json` config. */ /**A list of valid question ids from the `questions.jsonc` config. */
questions:string[], questions:string[],
/**All settings related to the ticket channel itself. */ /**All settings related to the ticket channel itself. */
channel:ODOptionsJsonConfig_TicketOptionChannelSettings, channel:ODOptionsJsonConfig_TicketOptionChannelSettings,
@@ -460,7 +459,7 @@ export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_Ba
} }
/**## ODOptionsJsonConfig_WebsiteOption `interface` /**## ODOptionsJsonConfig_WebsiteOption `interface`
* This interface is an object which has all website properties for options in the `options.json` config! * All properties for website options in the `options.jsonc` config!
*/ */
export interface ODOptionsJsonConfig_WebsiteOption extends ODOptionsJsonConfig_BaseOption { export interface ODOptionsJsonConfig_WebsiteOption extends ODOptionsJsonConfig_BaseOption {
type:"website", type:"website",
@@ -469,7 +468,7 @@ export interface ODOptionsJsonConfig_WebsiteOption extends ODOptionsJsonConfig_B
} }
/**## ODOptionsJsonConfig_RoleOption `interface` /**## ODOptionsJsonConfig_RoleOption `interface`
* This interface is an object which has all reaction role properties for options in the `options.json` config! * All properties for reaction-role options in the `options.jsonc` config!
*/ */
export interface ODOptionsJsonConfig_RoleOption extends ODOptionsJsonConfig_BaseOption { export interface ODOptionsJsonConfig_RoleOption extends ODOptionsJsonConfig_BaseOption {
type:"role", type:"role",
@@ -484,18 +483,28 @@ export interface ODOptionsJsonConfig_RoleOption extends ODOptionsJsonConfig_Base
addOnMemberJoin:boolean addOnMemberJoin:boolean
} }
/**## ODOptionsJsonConfig_OptionsData `type` /**## ODOptionsJsonConfig_SubPanelOption `interface`
* All contents of the `options.json` config file. * All properties for sub-panel options in the `options.jsonc` config!
*/ */
export type ODOptionsJsonConfig_OptionsData = (ODOptionsJsonConfig_TicketOption|ODOptionsJsonConfig_WebsiteOption|ODOptionsJsonConfig_RoleOption)[] export interface ODOptionsJsonConfig_SubPanelOption extends ODOptionsJsonConfig_BaseOption {
type:"sub-panel",
button:ODOptionsJsonConfig_OptionButtonSettings,
/**The panel ID of the sub-panel to show when the button is clicked. */
subPanelId:string
}
/**## ODOptionsJsonConfig_OptionsData `type`
* All contents of the `options.jsonc` config file.
*/
export type ODOptionsJsonConfig_OptionsData = (ODOptionsJsonConfig_TicketOption|ODOptionsJsonConfig_WebsiteOption|ODOptionsJsonConfig_RoleOption|ODOptionsJsonConfig_SubPanelOption)[]
/////////////////////////////////////// ///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES // CONFIG STRUCTURES, VALUES & TYPES
// --> panels.json // --> panels.jsonc
/////////////////////////////////////// ///////////////////////////////////////
/**## ODPanelsJsonConfig_PanelEmbedSettings `interface` /**## ODPanelsJsonConfig_PanelEmbedSettings `interface`
* This interface is an object which has all message embed settings for panels in the `panels.json` config! * This interface is an object which has all message embed settings for panels in the `panels.jsonc` config!
*/ */
export interface ODPanelsJsonConfig_PanelEmbedSettings { export interface ODPanelsJsonConfig_PanelEmbedSettings {
/**Is this embed enabled? */ /**Is this embed enabled? */
@@ -535,6 +544,8 @@ export interface ODPanelsJsonConfig_PanelEmbedSettings {
export interface ODPanelsJsonConfig_PanelSettings { export interface ODPanelsJsonConfig_PanelSettings {
/**The placeholder used in the dropdown when enabled. */ /**The placeholder used in the dropdown when enabled. */
dropdownPlaceholder:string, dropdownPlaceholder:string,
/**The maximum amount of option buttons before starting a new row. */
maximumButtonsPerRow:number
/**Enable a max tickets warning in the text contents. */ /**Enable a max tickets warning in the text contents. */
enableMaxTicketsWarningInText:boolean, enableMaxTicketsWarningInText:boolean,
@@ -554,7 +565,7 @@ export interface ODPanelsJsonConfig_PanelSettings {
} }
/**## ODPanelsJsonConfig_Panel `interface` /**## ODPanelsJsonConfig_Panel `interface`
* This interface is an object which has all properties for panels in the `panels.json` config! * This interface is an object which has all properties for panels in the `panels.jsonc` config!
*/ */
export interface ODPanelsJsonConfig_Panel { export interface ODPanelsJsonConfig_Panel {
/**The id of this panel. */ /**The id of this panel. */
@@ -563,7 +574,7 @@ export interface ODPanelsJsonConfig_Panel {
name:string, name:string,
/**When enabled, the panel uses a dropdown instead of buttons. */ /**When enabled, the panel uses a dropdown instead of buttons. */
dropdown:boolean, dropdown:boolean,
/**A list of valid options ids from the `options.json` config. */ /**A list of valid options ids from the `options.jsonc` config. */
options:string[], options:string[],
/**The raw text contents of this panel. (empty for embed only) */ /**The raw text contents of this panel. (empty for embed only) */
@@ -575,19 +586,19 @@ export interface ODPanelsJsonConfig_Panel {
} }
/**## ODPanelsJsonConfig_PanelsData `type` /**## ODPanelsJsonConfig_PanelsData `type`
* All contents of the `panels.json` config file. * All contents of the `panels.jsonc` config file.
*/ */
export type ODPanelsJsonConfig_PanelsData = ODPanelsJsonConfig_Panel[] export type ODPanelsJsonConfig_PanelsData = ODPanelsJsonConfig_Panel[]
/////////////////////////////////////// ///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES // CONFIG STRUCTURES, VALUES & TYPES
// --> questions.json // --> questions.jsonc
/////////////////////////////////////// ///////////////////////////////////////
/**## ODQuestionsJsonConfig_QuestionLengthSettings `interface` /**## ODQuestionsJsonConfig_TextLengthLimits `interface`
* This interface is a collection of settings related to length validation in a question. * This interface is a collection of settings related to length validation in a question.
*/ */
export interface ODQuestionsJsonConfig_QuestionLengthSettings { export interface ODQuestionsJsonConfig_TextLengthLimits {
/**Enable text length verification. */ /**Enable text length verification. */
enabled:boolean, enabled:boolean,
/**The minimum text input length. */ /**The minimum text input length. */
@@ -596,48 +607,138 @@ export interface ODQuestionsJsonConfig_QuestionLengthSettings {
max:number max:number
} }
/**## ODQuestionsJsonConfig_CheckboxLimits `interface`
* The required amount of checkboxes validation in a question.
*/
export interface ODQuestionsJsonConfig_CheckboxLimits {
/**Enable checkbox limits. */
enabled:boolean,
/**The minimum amount of selected checkboxes. */
min:number,
/**The maximum amount of selected checkboxes. */
max:number
}
/**## ODQuestionsJsonConfig_DropdownChoice `interface`
* A dropdown choice used in `ODQuestionsJsonConfig_DropdownQuestion`
*/
export interface ODQuestionsJsonConfig_DropdownChoice {
/**The title of the choice. */
title:string,
/**The optional description of the choice. (Leave empty for none) */
description:string,
/**The optional emoji of the choice. (Leave empty for none) */
emoji:string
}
/**## ODQuestionsJsonConfig_RadioCheckboxChoice `interface`
* A radio/checkbox choice used in `ODQuestionsJsonConfig_RadioSelectQuestion` & `ODQuestionsJsonConfig_CheckboxSelectQuestion`
*/
export interface ODQuestionsJsonConfig_RadioCheckboxChoice {
/**The title of the choice. */
title:string,
/**The optional description of the choice. (Leave empty for none) */
description:string,
/**Is this choice selected by default? */
selectedByDefault:boolean
}
/**## ODQuestionsJsonConfig_BaseQuestion `interface` /**## ODQuestionsJsonConfig_BaseQuestion `interface`
* This interface is an object which has all universal properties for questions in the `questions.json` config! * This interface is an object which has all universal properties for questions in the `questions.jsonc` config!
*/ */
export interface ODQuestionsJsonConfig_BaseQuestion { export interface ODQuestionsJsonConfig_BaseQuestion {
/**The id of this question. */ /**The id of this question. */
id:string, id:string,
/**The name of this question. */ /**The name of this question. */
name:string, name:string,
/**The description of this question. (Leave empty for none) */
description:string,
/**The type of this question. */ /**The type of this question. */
type:"short"|"paragraph", type:"short"|"paragraph"|"text-display"|"dropdown"|"radio-select"|"checkbox-select",
/**Is this question required? */ /**Is this question required? */
required:boolean, required:boolean,
} }
/**## ODQuestionsJsonConfig_TextDisplayQuestion `interface`
* All properties for a text-display in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_TextDisplayQuestion {
/**The id of this text-display. */
id:string,
/**The type of this question. */
type:"text-display",
/**The text contents to show in the modal. */
textContents:string
}
/**## ODQuestionsJsonConfig_ShortQuestion `interface` /**## ODQuestionsJsonConfig_ShortQuestion `interface`
* This interface is an object which has all properties for short questions in the `questions.json` config! * All properties for short questions in the `questions.jsonc` config!
*/ */
export interface ODQuestionsJsonConfig_ShortQuestion extends ODQuestionsJsonConfig_BaseQuestion { export interface ODQuestionsJsonConfig_ShortQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"short",
/**A placeholder for the question. */ /**A placeholder for the question. */
placeholder:string, placeholder:string,
/**A collection of settings related to length validation in a question. */ /**A collection of settings related to length validation in a question. */
length:ODQuestionsJsonConfig_QuestionLengthSettings length:ODQuestionsJsonConfig_TextLengthLimits
} }
/**## ODQuestionsJsonConfig_ParagraphQuestion `interface` /**## ODQuestionsJsonConfig_ParagraphQuestion `interface`
* This interface is an object which has all properties for paragraph questions in the `questions.json` config! * All properties for paragraph questions in the `questions.jsonc` config!
*/ */
export interface ODQuestionsJsonConfig_ParagraphQuestion extends ODQuestionsJsonConfig_BaseQuestion { export interface ODQuestionsJsonConfig_ParagraphQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"paragraph",
/**A placeholder for the question. */ /**A placeholder for the question. */
placeholder:string, placeholder:string,
/**A collection of settings related to length validation in a question. */ /**A collection of settings related to length validation in a question. */
length:ODQuestionsJsonConfig_QuestionLengthSettings length:ODQuestionsJsonConfig_TextLengthLimits
}
/**## ODQuestionsJsonConfig_DropdownQuestion `interface`
* All properties for dropdown questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_DropdownQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"dropdown",
/**A placeholder for the dropdown. */
placeholder:string,
/**A list of maximum 25 dropdown choices. */
choices:ODQuestionsJsonConfig_DropdownChoice[]
}
/**## ODQuestionsJsonConfig_RadioSelectQuestion `interface`
* All properties for radio select questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_RadioSelectQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"radio-select",
/**A list of minimum 2, maximum 10 radio choices. */
choices:ODQuestionsJsonConfig_RadioCheckboxChoice[]
}
/**## ODQuestionsJsonConfig_CheckboxSelectQuestion `interface`
* All properties for checkbox select questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_CheckboxSelectQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"checkbox-select",
/**Verify the checked amount of checkboxes with a minimum & maximum. */
limits:ODQuestionsJsonConfig_CheckboxLimits
/**A list of minimum 1, maximum 10 checkbox choices. */
choices:ODQuestionsJsonConfig_RadioCheckboxChoice[]
} }
/**## ODQuestionsJsonConfig_QuestionsData `type` /**## ODQuestionsJsonConfig_QuestionsData `type`
* All contents of the `questions.json` config file. * All contents of the `questions.jsonc` config file.
*/ */
export type ODQuestionsJsonConfig_QuestionsData = (ODQuestionsJsonConfig_ShortQuestion|ODQuestionsJsonConfig_ParagraphQuestion)[] export type ODQuestionsJsonConfig_QuestionsData = (
ODQuestionsJsonConfig_ShortQuestion|
ODQuestionsJsonConfig_ParagraphQuestion|
ODQuestionsJsonConfig_TextDisplayQuestion|
ODQuestionsJsonConfig_DropdownQuestion|
ODQuestionsJsonConfig_RadioSelectQuestion|
ODQuestionsJsonConfig_CheckboxSelectQuestion
)[]
/////////////////////////////////////// ///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES // CONFIG STRUCTURES, VALUES & TYPES
// --> transcripts.json // --> transcripts.jsonc
/////////////////////////////////////// ///////////////////////////////////////
/**## ODTranscriptsJsonConfig_TranscriptsTextLayout `interface` /**## ODTranscriptsJsonConfig_TranscriptsTextLayout `interface`
@@ -712,7 +813,7 @@ export interface ODTranscriptsJsonConfig_TranscriptsHtmlLayout {
} }
/**## ODTranscriptsJsonConfig_TranscriptsData `interface` /**## ODTranscriptsJsonConfig_TranscriptsData `interface`
* All contents of the `transcripts.json` config file. * All contents of the `transcripts.jsonc` config file.
*/ */
export interface ODTranscriptsJsonConfig_TranscriptsData { export interface ODTranscriptsJsonConfig_TranscriptsData {
/**All general settings related to transcripts. */ /**All general settings related to transcripts. */
@@ -760,27 +861,27 @@ export interface ODTranscriptsJsonConfig_TranscriptsData {
*/ */
export class ODMappedConfigManager extends api.ODConfigManager<ODConfigManagerIdMappings> {} export class ODMappedConfigManager extends api.ODConfigManager<ODConfigManagerIdMappings> {}
/**## ODGeneralJsonConfig `class /**## ODGeneralJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/general.json` config file * A special class with types for the Open Ticket `config/general.jsonc` config file
*/ */
export class ODGeneralJsonConfig extends api.ODJsonConfig<ODGeneralJsonConfig_GeneralData> {} export class ODGeneralJsonCommentsConfig extends api.ODJsonCommentsConfig<ODGeneralJsonConfig_GeneralData> {}
/**## ODQuestionsJsonConfig `class /**## ODQuestionsJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/questions.json` config file * A special class with types for the Open Ticket `config/questions.jsonc` config file
*/ */
export class ODQuestionsJsonConfig extends api.ODJsonConfig<ODQuestionsJsonConfig_QuestionsData> {} export class ODQuestionsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODQuestionsJsonConfig_QuestionsData> {}
/**## ODOptionsJsonConfig `class /**## ODOptionsJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/options.json` config file * A special class with types for the Open Ticket `config/options.jsonc` config file
*/ */
export class ODOptionsJsonConfig extends api.ODJsonConfig<ODOptionsJsonConfig_OptionsData> {} export class ODOptionsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODOptionsJsonConfig_OptionsData> {}
/**## ODPanelsJsonConfig `class /**## ODPanelsJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/panels.json` config file * A special class with types for the Open Ticket `config/panels.jsonc` config file
*/ */
export class ODPanelsJsonConfig extends api.ODJsonConfig<ODPanelsJsonConfig_PanelsData> {} export class ODPanelsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODPanelsJsonConfig_PanelsData> {}
/**## ODTranscriptsJsonConfig `class /**## ODTranscriptsJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/transcripts.json` config file * A special class with types for the Open Ticket `config/transcripts.jsonc` config file
*/ */
export class ODTranscriptsJsonConfig extends api.ODJsonConfig<ODTranscriptsJsonConfig_TranscriptsData> {} export class ODTranscriptsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODTranscriptsJsonConfig_TranscriptsData> {}
+5 -5
View File
@@ -6,21 +6,21 @@ import * as api from "@open-discord-bots/framework/api"
export interface ODOpenTicketFuseList { export interface ODOpenTicketFuseList {
/**Load the default Open Ticket ticket priority levels. */ /**Load the default Open Ticket ticket priority levels. */
priorityLoading:boolean, priorityLoading:boolean,
/**Load the default Open Ticket questions (from `config/questions.json`) */ /**Load the default Open Ticket questions (from `config/questions.jsonc`) */
questionLoading:boolean, questionLoading:boolean,
/**Load the default Open Ticket options (from `config/options.json`) */ /**Load the default Open Ticket options (from `config/options.jsonc`) */
optionLoading:boolean, optionLoading:boolean,
/**Load the default Open Ticket panels (from `config/panels.json`) */ /**Load the default Open Ticket panels (from `config/panels.jsonc`) */
panelLoading:boolean, panelLoading:boolean,
/**Load the default Open Ticket tickets (from `database/tickets.json`) */ /**Load the default Open Ticket tickets (from `database/tickets.json`) */
ticketLoading:boolean, ticketLoading:boolean,
/**Load the default Open Ticket reaction roles (from `config/options.json`) */ /**Load the default Open Ticket reaction roles (from `config/options.jsonc`) */
roleLoading:boolean, roleLoading:boolean,
/**Load the default Open Ticket blacklist (from `database/users.json`) */ /**Load the default Open Ticket blacklist (from `database/users.json`) */
blacklistLoading:boolean, blacklistLoading:boolean,
/**Load the default Open Ticket transcript compilers. */ /**Load the default Open Ticket transcript compilers. */
transcriptCompilerLoading:boolean, transcriptCompilerLoading:boolean,
/**Load the default Open Ticket transcript history (from `database/transcripts.json`) */ /**Load the default Open Ticket transcript history (from `database/transcripts.jsonc`) */
transcriptHistoryLoading:boolean, transcriptHistoryLoading:boolean,
/**The interval in milliseconds that are between autoclose timeout checkers. */ /**The interval in milliseconds that are between autoclose timeout checkers. */
autocloseCheckInterval:number, autocloseCheckInterval:number,
+95 -49
View File
@@ -1,9 +1,24 @@
import {opendiscord, api, utilities} from "../../index.js" import {opendiscord, api, utilities} from "../../index.js"
import fs from "fs" import fs from "fs"
import path from "path"
/**Check if the no-migration flag is active. */
function isMigrationAllowedFromFlag(){
return (!process.argv.includes("--no-migration") && !process.argv.includes("-nm"))
}
/**Read the global.json database raw to detect the last version of the bot. */
function getRawLastVersion(){
const isDevDatabase = process.argv.includes("--dev-database") || process.argv.includes("-dd")
const globalDatabaseLocation = path.join(process.cwd(),(isDevDatabase) ? "./devdatabase/global.json" : "./database/global.json")
const rawData: api.ODJsonDatabaseStructure = JSON.parse(fs.readFileSync(globalDatabaseLocation).toString())
const lastVersion = rawData.find((d) => d.category == "opendiscord:last-version" && d.key == "opendiscord:version")?.value ?? null
return lastVersion as string|null
}
/**Check if migration is required. Returns the last version used in the database. */ /**Check if migration is required. Returns the last version used in the database. */
async function isMigrationRequired(): Promise<false|api.ODVersion> { async function isMigrationRequired(): Promise<false|api.ODVersion> {
const rawVersion = await opendiscord.databases.get("opendiscord:global").get("opendiscord:last-version","opendiscord:version") const rawVersion = getRawLastVersion()
if (!rawVersion) return false if (!rawVersion) return false
const version = api.ODVersion.fromString("opendiscord:last-version",rawVersion) const version = api.ODVersion.fromString("opendiscord:last-version",rawVersion)
if (opendiscord.versions.get("opendiscord:version").compare(version) == "higher"){ if (opendiscord.versions.get("opendiscord:version").compare(version) == "higher"){
@@ -20,47 +35,6 @@ async function saveAllVersionsToDatabase(){
}) })
} }
export async function loadVersionMigrationSystem(){
//ENTER MIGRATION CONTEXT
await preloadMigrationContext()
const lastVersion = await isMigrationRequired()
//save last version to database (OR set to current version if no migration is required)
opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("opendiscord:last-version",opendiscord.versions.get("opendiscord:version").toString()))
if (lastVersion && !opendiscord.flags.get("opendiscord:no-migration").value){
//MIGRATION IS REQUIRED
opendiscord.log("Detected old data!","info")
opendiscord.log("Starting closed API context...","debug")
await utilities.timer(600)
opendiscord.log("Migrating data to new version...","debug")
await loadAllVersionMigrations(lastVersion)
opendiscord.log("Stopping closed API context...","debug")
await utilities.timer(400)
opendiscord.log("All data is now up to date!","info")
await utilities.timer(200)
console.log("---------------------------------------------------------------------")
}
saveAllVersionsToDatabase()
//DEFAULT FLAGS
if (opendiscord.flags.exists("opendiscord:no-plugins") && opendiscord.flags.get("opendiscord:no-plugins").value) opendiscord.sharedFuses.setFuse("pluginLoading",false)
if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.sharedFuses.setFuse("softPluginLoading",true)
if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.sharedFuses.setFuse("crashOnError",true)
if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value){
opendiscord.sharedFuses.setFuse("forceSlashCommandRegistration",true)
opendiscord.sharedFuses.setFuse("forceContextMenuRegistration",true)
}
if (opendiscord.flags.exists("opendiscord:silent") && opendiscord.flags.get("opendiscord:silent").value) opendiscord.console.silent = true
//LEAVE MIGRATION CONTEXT
await unloadMigrationContext()
return lastVersion
}
/**Initialize the migration context by loading the built-in flags, configs & databases. */ /**Initialize the migration context by loading the built-in flags, configs & databases. */
async function preloadMigrationContext(){ async function preloadMigrationContext(){
opendiscord.debug.debug("-- MIGRATION CONTEXT START --") opendiscord.debug.debug("-- MIGRATION CONTEXT START --")
@@ -73,6 +47,52 @@ async function preloadMigrationContext(){
opendiscord.debug.visible = true opendiscord.debug.visible = true
} }
export async function loadVersionMigrationSystem(){
const lastVersion = await isMigrationRequired()
//save last version in version manager (OR set to current version if no migration is required)
opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("opendiscord:last-version",opendiscord.versions.get("opendiscord:version").toString()))
//MIGRATION IS REQUIRED
if (lastVersion && isMigrationAllowedFromFlag()){
//BEFORE STARTUP MIGRATION
opendiscord.log("Detected old data!","info")
await loadBeforeStartupMigrations(lastVersion)
}
//ENTER MIGRATION CONTEXT (must be separate for flags to work)
await preloadMigrationContext()
if (lastVersion && isMigrationAllowedFromFlag()){
//CONTEXT MIGRATION
opendiscord.log("Starting restricted API context...","debug")
await utilities.timer(600)
opendiscord.log("Migrating data to new version...","debug")
await loadContextMigrations(lastVersion)
opendiscord.log("Stopping restricted API context...","debug")
await utilities.timer(400)
opendiscord.log("All data is now up to date!","info")
await utilities.timer(200)
console.log("---------------------------------------------------------------------")
}
saveAllVersionsToDatabase()
//SET FUSES & PROPERTIES OF SPECIAL FLAGS
if (opendiscord.flags.exists("opendiscord:no-plugins") && opendiscord.flags.get("opendiscord:no-plugins").value) opendiscord.sharedFuses.setFuse("pluginLoading",false)
if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.sharedFuses.setFuse("softPluginLoading",true)
if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.sharedFuses.setFuse("crashOnError",true)
if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value){
opendiscord.sharedFuses.setFuse("forceSlashCommandRegistration",true)
opendiscord.sharedFuses.setFuse("forceContextMenuRegistration",true)
}
if (opendiscord.flags.exists("opendiscord:silent") && opendiscord.flags.get("opendiscord:silent").value) opendiscord.console.silent = true
//LEAVE MIGRATION CONTEXT
await unloadMigrationContext()
return lastVersion
}
/**Unload the migration context to start the bot normally. */ /**Unload the migration context to start the bot normally. */
async function unloadMigrationContext(){ async function unloadMigrationContext(){
opendiscord.debug.visible = false opendiscord.debug.visible = false
@@ -98,8 +118,8 @@ function createMigrationBackup(){
else fs.cpSync("./database/","./.backup/database/",{force:true,recursive:true}) else fs.cpSync("./database/","./.backup/database/",{force:true,recursive:true})
} }
/**Execute all version migration functions which are handled in the restricted migration context. */ /**Execute all version migration functions which are handled before any flags, configs or databases are loaded. */
async function loadAllVersionMigrations(lastVersion:api.ODVersion){ async function loadBeforeStartupMigrations(lastVersion:api.ODVersion){
const migrations = (await import("./migration.js")).migrations const migrations = (await import("./migration.js")).migrations
migrations.sort((a,b) => { migrations.sort((a,b) => {
const comparison = a.version.compare(b.version) const comparison = a.version.compare(b.version)
@@ -114,10 +134,36 @@ async function loadAllVersionMigrations(lastVersion:api.ODVersion){
for (const migration of migrations){ for (const migration of migrations){
if (migration.version.compare(lastVersion) == "higher"){ if (migration.version.compare(lastVersion) == "higher"){
const success = await migration.migrate() const success = await migration.migrateBeforeStartup()
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[ if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
{key:"success",value:success ? "true" : "false"}, {key:"success",value:success ? "true" : "false"},
{key:"afterInit",value:"false"} {key:"type",value:"before-startup"}
])
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
}
}
}
/**Execute all version migration functions which are handled in the restricted migration context. */
async function loadContextMigrations(lastVersion:api.ODVersion){
const migrations = (await import("./migration.js")).migrations
migrations.sort((a,b) => {
const comparison = a.version.compare(b.version)
if (comparison == "equal") return 0
else if (comparison == "higher") return 1
else return -1
})
if (migrations.length > 0){
//create backup of config & database
createMigrationBackup()
}
for (const migration of migrations){
if (migration.version.compare(lastVersion) == "higher"){
const success = await migration.migrateInContext()
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
{key:"success",value:success ? "true" : "false"},
{key:"type",value:"restricted-context"}
]) ])
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.") else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
} }
@@ -125,7 +171,7 @@ async function loadAllVersionMigrations(lastVersion:api.ODVersion){
} }
/**Execute all version migration functions which are handled in the normal startup sequence. */ /**Execute all version migration functions which are handled in the normal startup sequence. */
export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersion){ export async function loadAfterStartupMigrations(lastVersion:api.ODVersion){
const migrations = (await import("./migration.js")).migrations const migrations = (await import("./migration.js")).migrations
migrations.sort((a,b) => { migrations.sort((a,b) => {
const comparison = a.version.compare(b.version) const comparison = a.version.compare(b.version)
@@ -140,10 +186,10 @@ export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersio
for (const migration of migrations){ for (const migration of migrations){
if (migration.version.compare(lastVersion) == "higher"){ if (migration.version.compare(lastVersion) == "higher"){
const success = await migration.migrateAfterInit() const success = await migration.migrateAfterStartup()
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[ if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
{key:"success",value:success ? "true" : "false"}, {key:"success",value:success ? "true" : "false"},
{key:"afterInit",value:"true"} {key:"type",value:"after-startup"}
]) ])
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.") else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
} }
+306 -102
View File
@@ -1,147 +1,351 @@
import { opendiscord, api, utilities } from "../../index.js" import { opendiscord, api, utilities } from "../../index.js"
import fs from "fs"
import path from "path"
export const migrations = [ export const migrations = [
//MIGRATE TO v4.0.0 //MIGRATE TO v4.0.0
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.0"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.0"),{}),
//MIGRATE TO v4.0.1 //MIGRATE TO v4.0.1
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.1"),async () => {},async () => { new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.1"),{
//AFTER INIT MIGRATION afterStartupMigrate:async () => {
//add opendiscord:panel-message properties for all existing panels.
//add opendiscord:panel-message properties for all existing panels. const globalDatabase = opendiscord.databases.get("opendiscord:global")
const globalDatabase = opendiscord.databases.get("opendiscord:global") for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){
for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){ globalDatabase.set("opendiscord:panel-message",panel.key,panel.value)
globalDatabase.set("opendiscord:panel-message",panel.key,panel.value) }
} }
}), }),
//MIGRATE TO v4.0.2 //MIGRATE TO v4.0.2
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.2"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.2"),{}),
//MIGRATE TO v4.0.3 //MIGRATE TO v4.0.3
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.3"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.3"),{}),
//MIGRATE TO v4.0.4 //MIGRATE TO v4.0.4
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.4"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.4"),{}),
//MIGRATE TO v4.0.5 //MIGRATE TO v4.0.5
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.5"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.5"),{}),
//MIGRATE TO v4.0.6 //MIGRATE TO v4.0.6
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.6"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.6"),{}),
//MIGRATE TO v4.0.7 //MIGRATE TO v4.0.7
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.7"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.7"),{}),
//MIGRATE TO v4.1.0 //MIGRATE TO v4.1.0
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.0"),async () => {},async () => { new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.0"),{
//AFTER INIT MIGRATION afterStartupMigrate:async () => {
//migrate config
const generalConfig = opendiscord.configs.get("opendiscord:general")
const optionConfig = opendiscord.configs.get("opendiscord:options")
//migrate config if (!generalConfig.data.status.state){
const generalConfig = opendiscord.configs.get("opendiscord:general") //only migrate config when it hasn't been done manually by the user.
const optionConfig = opendiscord.configs.get("opendiscord:options")
if (!generalConfig.data.status.state){ if (!generalConfig.data["_INFO"]) throw new api.ODSystemError("Couldn't find general.json '_INFO' category.")
//only migrate config when it hasn't been done manually by the user. generalConfig.data["_INFO"].version = "open-ticket-v4.1.0"
if (!generalConfig.data._INFO) throw new api.ODSystemError("Couldn't find general.json '_INFO' category.") if (!generalConfig.data.status) throw new api.ODSystemError("Couldn't find general.json 'status' category.")
generalConfig.data._INFO.version = "open-ticket-v4.1.0" generalConfig.data.status.mode = generalConfig.data.status["status"] ?? "online"
generalConfig.data.status.state = ""
delete generalConfig.data.status["status"]
if (!generalConfig.data.status) throw new api.ODSystemError("Couldn't find general.json 'status' category.") if (!generalConfig.data["system"]) throw new api.ODSystemError("Couldn't find general.json 'system' category.")
generalConfig.data.status.mode = generalConfig.data.status["status"] ?? "online" generalConfig.data["system"].displayFieldsWithQuestions = false
generalConfig.data.status.state = "" generalConfig.data["system"].showGlobalAdminsInPanelRoles = false
delete generalConfig.data.status["status"] generalConfig.data["system"].alwaysShowReason = false
generalConfig.data["system"].pinEmoji = "📌"
generalConfig.data["system"].askPriorityOnTicketCreation = false
generalConfig.data["system"].disableAutocloseAfterReopen = true
generalConfig.data["system"].autodeleteRequiresClosedTicket = true
generalConfig.data["system"].adminOnlyDeleteWithoutTranscript = true
generalConfig.data["system"].allowCloseBeforeMessage = false
generalConfig.data["system"].allowCloseBeforeAdminMessage = true
generalConfig.data["system"].pinFirstTicketMessage = false
if (!generalConfig.data.system) throw new api.ODSystemError("Couldn't find general.json 'system' category.") generalConfig.data["system"].channelTopic = {
generalConfig.data.system.displayFieldsWithQuestions = false showOptionName:true,
generalConfig.data.system.showGlobalAdminsInPanelRoles = false showOptionDescription:false,
generalConfig.data.system.alwaysShowReason = false showOptionTopic:true,
generalConfig.data.system.pinEmoji = "📌" showPriority:false,
generalConfig.data.system.askPriorityOnTicketCreation = false showClosed:true,
generalConfig.data.system.disableAutocloseAfterReopen = true showClaimed:false,
generalConfig.data.system.autodeleteRequiresClosedTicket = true showPinned:false,
generalConfig.data.system.adminOnlyDeleteWithoutTranscript = true showCreator:false,
generalConfig.data.system.allowCloseBeforeMessage = false showParticipants:false
generalConfig.data.system.allowCloseBeforeAdminMessage = true
generalConfig.data.system.pinFirstTicketMessage = false
generalConfig.data.system.channelTopic = {
showOptionName:true,
showOptionDescription:false,
showOptionTopic:true,
showPriority:false,
showClosed:true,
showClaimed:false,
showPinned:false,
showCreator:false,
showParticipants:false
}
if (!generalConfig.data.system.permissions) throw new api.ODSystemError("Couldn't find general.json 'system.permissions' category.")
generalConfig.data.system.permissions.transfer = "admin"
generalConfig.data.system.permissions.topic = "admin"
generalConfig.data.system.permissions.priority = "admin"
if (!generalConfig.data.system.messages) throw new api.ODSystemError("Couldn't find general.json 'system.messages' category.")
generalConfig.data.system.messages.transferring = {dm:false,logs:true}
generalConfig.data.system.messages.topicChange = {dm:false,logs:true}
generalConfig.data.system.messages.priorityChange = {dm:false,logs:true}
generalConfig.data.system.messages.reactionRole = generalConfig.data.system.messages["roleAdding"] ?? {dm:false,logs:true}
delete generalConfig.data.system.messages["roleAdding"]
delete generalConfig.data.system.messages["roleRemoving"]
for (const option of optionConfig.data){
if (option.type != "ticket") continue
option.channel.topic = option.channel["description"] ?? ""
delete option.channel["description"]
option.slowMode = {
enabled:false,
slowModeSeconds:20
} }
if (!generalConfig.data["system"].permissions) throw new api.ODSystemError("Couldn't find general.json 'system.permissions' category.")
generalConfig.data["system"].permissions.transfer = "admin"
generalConfig.data["system"].permissions.topic = "admin"
generalConfig.data["system"].permissions.priority = "admin"
if (!generalConfig.data["system"].messages) throw new api.ODSystemError("Couldn't find general.json 'system.messages' category.")
generalConfig.data["system"].messages.transferring = {dm:false,logs:true}
generalConfig.data["system"].messages.topicChange = {dm:false,logs:true}
generalConfig.data["system"].messages.priorityChange = {dm:false,logs:true}
generalConfig.data["system"].messages.reactionRole = generalConfig.data["system"].messages["roleAdding"] ?? {dm:false,logs:true}
delete generalConfig.data["system"].messages["roleAdding"]
delete generalConfig.data["system"].messages["roleRemoving"]
for (const option of optionConfig.data){
if (option.type != "ticket") continue
option.channel.topic = option.channel["description"] ?? ""
delete option.channel["description"]
option.slowMode = {
enabled:false,
slowModeSeconds:20
}
}
await generalConfig.save()
await optionConfig.save()
} }
await generalConfig.save() //migrate database
await optionConfig.save() const optionDatabase = opendiscord.databases.get("opendiscord:options")
} const ticketDatabase = opendiscord.databases.get("opendiscord:tickets")
//migrate database for (const option of (await optionDatabase.getCategory("opendiscord:used-option") ?? [])){
const optionDatabase = opendiscord.databases.get("opendiscord:options") const optionData = option.value
const ticketDatabase = opendiscord.databases.get("opendiscord:tickets")
for (const option of (await optionDatabase.getCategory("opendiscord:used-option") ?? [])){ const topicData = optionData.data.find((d) => d.id == "opendiscord:channel-description")
const optionData = option.value if (topicData) topicData.id = "opendiscord:channel-topic"
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-enabled")) optionData.data.push({id:"opendiscord:slowmode-enabled",value:false})
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-seconds")) optionData.data.push({id:"opendiscord:slowmode-seconds",value:20})
const topicData = optionData.data.find((d) => d.id == "opendiscord:channel-description") optionDatabase.set("opendiscord:used-option",option.key,optionData)
if (topicData) topicData.id = "opendiscord:channel-topic" }
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-enabled")) optionData.data.push({id:"opendiscord:slowmode-enabled",value:false})
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-seconds")) optionData.data.push({id:"opendiscord:slowmode-seconds",value:20})
optionDatabase.set("opendiscord:used-option",option.key,optionData) for (const ticket of (await ticketDatabase.getCategory("opendiscord:ticket") ?? [])){
} const ticketData = ticket.value
for (const ticket of (await ticketDatabase.getCategory("opendiscord:ticket") ?? [])){ if (!ticketData.data.find((d) => d.id == "opendiscord:previous-creators")) ticketData.data.push({id:"opendiscord:previous-creators",value:[]})
const ticketData = ticket.value if (!ticketData.data.find((d) => d.id == "opendiscord:reopened")) ticketData.data.push({id:"opendiscord:reopened",value:false})
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-by")) ticketData.data.push({id:"opendiscord:reopened-by",value:null})
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-on")) ticketData.data.push({id:"opendiscord:reopened-on",value:null})
if (!ticketData.data.find((d) => d.id == "opendiscord:priority")) ticketData.data.push({id:"opendiscord:priority",value:-1})
if (!ticketData.data.find((d) => d.id == "opendiscord:topic")) ticketData.data.push({id:"opendiscord:topic",value:""})
if (!ticketData.data.find((d) => d.id == "opendiscord:message-sent")) ticketData.data.push({id:"opendiscord:message-sent",value:true})
if (!ticketData.data.find((d) => d.id == "opendiscord:admin-message-sent")) ticketData.data.push({id:"opendiscord:admin-message-sent",value:true})
if (!ticketData.data.find((d) => d.id == "opendiscord:previous-creators")) ticketData.data.push({id:"opendiscord:previous-creators",value:[]}) ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened")) ticketData.data.push({id:"opendiscord:reopened",value:false}) }
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-by")) ticketData.data.push({id:"opendiscord:reopened-by",value:null})
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-on")) ticketData.data.push({id:"opendiscord:reopened-on",value:null})
if (!ticketData.data.find((d) => d.id == "opendiscord:priority")) ticketData.data.push({id:"opendiscord:priority",value:-1})
if (!ticketData.data.find((d) => d.id == "opendiscord:topic")) ticketData.data.push({id:"opendiscord:topic",value:""})
if (!ticketData.data.find((d) => d.id == "opendiscord:message-sent")) ticketData.data.push({id:"opendiscord:message-sent",value:true})
if (!ticketData.data.find((d) => d.id == "opendiscord:admin-message-sent")) ticketData.data.push({id:"opendiscord:admin-message-sent",value:true})
ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
} }
}), }),
//MIGRATE TO v4.1.1 //MIGRATE TO v4.1.1
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.1"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.1"),{}),
//MIGRATE TO v4.1.2 //MIGRATE TO v4.1.2
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.2"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.2"),{}),
//MIGRATE TO v4.1.3 //MIGRATE TO v4.1.3
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.3"),async () => {},async () => {}), new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.3"),{}),
//MIGRATE TO v4.2.0
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.2.0"),{
beforeStartupMigrate:async () => {
const isDevconfig = (process.argv.includes("--dev-config") || process.argv.includes("-dc"))
//transfer config files to .jsonc
const configDir = path.join(process.cwd(),(isDevconfig) ? "./devconfig/" : "./config/")
for (const file of fs.readdirSync(configDir).filter((f) => f.endsWith(".json"))){
try{
fs.copyFileSync(path.join(configDir,file),path.join(configDir,file.replace(".json",".jsonc")))
fs.rmSync(path.join(configDir,file))
}catch(err){
process.emit("uncaughtException",err)
}
}
},
afterStartupMigrate:async () => {
//migrate config
const generalConfig = opendiscord.configs.get("opendiscord:general")
const questionConfig = opendiscord.configs.get("opendiscord:questions")
const optionConfig = opendiscord.configs.get("opendiscord:options")
const panelConfig = opendiscord.configs.get("opendiscord:panels")
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
if (!generalConfig.data.ticketSystem){
//only migrate config when it hasn't been done manually by the user.
if (!generalConfig.data["_INFO"]) throw new api.ODSystemError("Couldn't find general.jsonc '_INFO' category.")
delete generalConfig.data["_INFO"]
generalConfig.data._CONFIG_VERSION = "open-ticket-v4.2.0"
if (!generalConfig.data["system"]) throw new api.ODSystemError("Couldn't find general.jsonc 'system' category.")
generalConfig.data.ticketSystem = generalConfig.data["system"]
generalConfig.data.ticketSystem.closeEmoji = "🔒"
generalConfig.data.ticketSystem.askPriorityOnTicketCreation = true
generalConfig.data.ticketSystem.enableCreateTicketForOtherUser = true
delete generalConfig.data["system"]
generalConfig.data.logs = generalConfig.data.ticketSystem["logs"]
delete generalConfig.data.ticketSystem["logs"]
generalConfig.data.logs.logMessages = generalConfig.data.ticketSystem["messages"]
delete generalConfig.data.ticketSystem["messages"]
generalConfig.data.permissions = generalConfig.data.ticketSystem["permissions"]
delete generalConfig.data.ticketSystem["permissions"]
generalConfig.data.permissions.transcripts = "admin"
//closed category
const closedCategory = {enabled:false,categoryId:"DISCORD_CATEGORY_ID"}
for (const option of optionConfig.data){
if (option.type != "ticket") continue
if (option.channel["closedCategory"] && /^\d+$/.test(option.channel["closedCategory"])){
closedCategory.enabled = true
closedCategory.categoryId = option.channel["closedCategory"]
}
}
generalConfig.data.ticketSystem.closedCategory = closedCategory
//backup category
const backupCategory = {enabled:false,categoryId:"DISCORD_CATEGORY_ID"}
for (const option of optionConfig.data){
if (option.type != "ticket") continue
if (option.channel["backupCategory"] && /^\d+$/.test(option.channel["backupCategory"])){
backupCategory.enabled = true
backupCategory.categoryId = option.channel["backupCategory"]
}
}
generalConfig.data.ticketSystem.backupCategory = backupCategory
//claimed categories
const claimedCategories: {user:string,category:string}[] = []
for (const option of optionConfig.data){
if (option.type != "ticket" || !Array.isArray(option.channel["claimedCategory"])) continue
for (const {user,category} of option.channel["claimedCategory"]){
if (typeof user == "string" && typeof category == "string" && /^\d+$/.test(user) && /^\d+$/.test(category) && !claimedCategories.find((c) => c.user == user)){
claimedCategories.push({user,category})
}
}
}
generalConfig.data.ticketSystem.claimedCategories = claimedCategories
//delete properties from options.jsonc
for (const option of optionConfig.data){
if (option.type != "ticket") continue
delete option.channel["closedCategory"]
delete option.channel["backupCategory"]
delete option.channel["claimedCategory"]
}
//update panels config:
for (const panel of panelConfig.data){
panel.settings.maximumButtonsPerRow = 5
}
//update questions config:
for (const question of questionConfig.data){
if (question.type !== "paragraph" && question.type !== "short") continue
question.description = ""
}
//add new sub-panel option example (for users to try)
optionConfig.data.push({
id:"example-sub-panel",
name:"Example Sub-Panel",
description:"This is an example of how to implement a sub-panel in Open Ticket.",
type:"sub-panel",
button:{
color:"gray",
label:"Sub-Panel Example",
emoji:"📋"
},
subPanelId:panelConfig.data[0]?.id ?? "example-panel"
})
//add new question examples (for users to try)
questionConfig.data.push(
{
id:"example-dropdown-question",
name:"Example Dropdown Question",
description:"This is a dropdown question.",
type:"dropdown",
required:false,
placeholder:"Choose your answer...",
choices:[
{title:"Choice A",description:"Apple",emoji:"🍎"},
{title:"Choice B",description:"Banana",emoji:"🍌"},
{title:"Choice C",description:"Orange",emoji:"🍊"},
{title:"Choice D",description:"Kiwi",emoji:"🥝"}
]
},
{
id:"example-radio-question",
name:"Example Radio Question",
description:"This is a radio select question.",
type:"radio-select",
required:true,
choices:[
{title:"Choice A",description:"Up",selectedByDefault:false},
{title:"Choice B",description:"Down",selectedByDefault:false},
{title:"Choice C",description:"Left",selectedByDefault:false},
{title:"Choice D",description:"Right",selectedByDefault:false}
]
},
{
id:"example-checkbox-question",
name:"Example Checkbox Question",
description:"This is a checkbox select question.",
type:"checkbox-select",
required:true,
limits:{
enabled:false,
min:0,
max:10
},
choices:[
{title:"Choice A",description:"Happiness",selectedByDefault:false},
{title:"Choice B",description:"Anger",selectedByDefault:false},
{title:"Choice C",description:"Sadness",selectedByDefault:false},
{title:"Choice D",description:"Fear",selectedByDefault:false}
]
},
{
id:"example-text-display-question",
type:"text-display",
textContents:"This is a text display. It isn't a question, but allows you to display a text, explaination or details."
}
)
await generalConfig.save()
await questionConfig.save()
await optionConfig.save()
await panelConfig.save()
await transcriptConfig.save()
}
//migrate database
const optionDatabase = opendiscord.databases.get("opendiscord:options")
const ticketDatabase = opendiscord.databases.get("opendiscord:tickets")
for (const option of (await optionDatabase.getCategory("opendiscord:used-option") ?? [])){
const optionData = option.value
optionData.data = optionData.data.filter((data) => (
data.id !== "opendiscord:channel-category-closed" &&
data.id !== "pendiscord:channel-category-backup" &&
data.id !== "opendiscord:channel-categories-claimed"
))
optionDatabase.set("opendiscord:used-option",option.key,optionData)
}
for (const ticket of (await ticketDatabase.getCategory("opendiscord:ticket") ?? [])){
const ticketData = ticket.value
if (!ticketData.data.find((d) => d.id == "opendiscord:channel-renamed")) ticketData.data.push({id:"opendiscord:channel-renamed",value:null})
ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
}
}
}),
] ]
+247 -100
View File
@@ -17,7 +17,7 @@ export async function loadAllConfigCheckerFunctions(){
} }
export async function loadAllConfigCheckerTranslations(){ export async function loadAllConfigCheckerTranslations(){
if ((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false){ if ((generalConfig && generalConfig.data.ticketSystem && generalConfig.data.ticketSystem.useTranslatedConfigChecker) ? generalConfig.data.ticketSystem.useTranslatedConfigChecker : false){
registerDefaultCheckerSystemTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate checker system text registerDefaultCheckerSystemTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate checker system text
registerDefaultCheckerMessageTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate checker messages registerDefaultCheckerMessageTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate checker messages
registerDefaultCheckerCustomTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate custom checker messages registerDefaultCheckerCustomTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate custom checker messages
@@ -25,7 +25,7 @@ export async function loadAllConfigCheckerTranslations(){
} }
//GLOBAL FUNCTIONS //GLOBAL FUNCTIONS
export const registerDefaultCheckerSystemTranslations = (tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager) => { export function registerDefaultCheckerSystemTranslations(tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager){
//SYSTEM //SYSTEM
tm.quickTranslate(lm,"checker.system.headerOpenTicket","other","opendiscord:header-projectname") //OPEN TICKET tm.quickTranslate(lm,"checker.system.headerOpenTicket","other","opendiscord:header-projectname") //OPEN TICKET
tm.quickTranslate(lm,"checker.system.typeError","other","opendiscord:type-error") // [ERROR] (ignore) tm.quickTranslate(lm,"checker.system.typeError","other","opendiscord:type-error") // [ERROR] (ignore)
@@ -42,7 +42,7 @@ export const registerDefaultCheckerSystemTranslations = (tm:api.ODMappedCheckerT
tm.quickTranslate(lm,"checker.system.dataMessages","other","opendiscord:data-message") // message tm.quickTranslate(lm,"checker.system.dataMessages","other","opendiscord:data-message") // message
} }
export const registerDefaultCheckerMessageTranslations = (tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager) => { export function registerDefaultCheckerMessageTranslations(tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager){
//STRUCTURES //STRUCTURES
tm.quickTranslate(lm,"checker.messages.invalidType","message","opendiscord:invalid-type") // This property needs to be the type: {0}! tm.quickTranslate(lm,"checker.messages.invalidType","message","opendiscord:invalid-type") // This property needs to be the type: {0}!
tm.quickTranslate(lm,"checker.messages.propertyMissing","message","opendiscord:property-missing") // The property {0} is missing from this object! tm.quickTranslate(lm,"checker.messages.propertyMissing","message","opendiscord:property-missing") // The property {0} is missing from this object!
@@ -117,7 +117,7 @@ export const registerDefaultCheckerMessageTranslations = (tm:api.ODMappedChecker
tm.quickTranslate(lm,"checker.messages.idNonExistent","message","opendiscord:id-non-existent") // The id {0} doesn't exist! tm.quickTranslate(lm,"checker.messages.idNonExistent","message","opendiscord:id-non-existent") // The id {0} doesn't exist!
} }
export const registerDefaultCheckerCustomTranslations = (tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager) => { export function registerDefaultCheckerCustomTranslations(tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager){
//CUSTOM //CUSTOM
tm.quickTranslate(lm,"checker.messages.invalidLanguage","message","opendiscord:invalid-language") // This is an invalid language! tm.quickTranslate(lm,"checker.messages.invalidLanguage","message","opendiscord:invalid-language") // This is an invalid language!
tm.quickTranslate(lm,"checker.messages.invalidButton","message","opendiscord:invalid-button") // This button needs to have at least an {0} or {1}! tm.quickTranslate(lm,"checker.messages.invalidButton","message","opendiscord:invalid-button") // This button needs to have at least an {0} or {1}!
@@ -128,13 +128,30 @@ export const registerDefaultCheckerCustomTranslations = (tm:api.ODMappedCheckerT
} }
//UTILITY FUNCTIONS //UTILITY FUNCTIONS
const createMsgStructure = (id:api.ODValidId,displayName:string) => { /**Get the panel ids from `panels.jsonc` before it has been checked by the config checker. */
function getUnsafePanelIds(): string[] {
const panelsConfig = opendiscord.configs.get("opendiscord:panels")
if (!Array.isArray(panelsConfig.data)) return []
const panelIds: string[] = []
for (const unsafePanel of panelsConfig.data){
if (unsafePanel["id"]) panelIds.push(unsafePanel["id"])
}
return panelIds
}
function createMsgStructure(id:api.ODValidId,displayName:string){
return new api.ODCheckerObjectStructure(id,{children:[ return new api.ODCheckerObjectStructure(id,{children:[
{key:"dm",checker:new api.ODCheckerBooleanStructure("opendiscord:msg-dm",{cliInitDefaultValue:false,cliDisplayName:"DM Enabled",cliDisplayDescription:"Will this action be sent in DM to the creator of the ticket?"})}, {key:"dm",checker:new api.ODCheckerBooleanStructure("opendiscord:msg-dm",{cliInitDefaultValue:false,cliDisplayName:"DM Enabled",cliDisplayDescription:"Will this action be sent in DM to the creator of the ticket?"})},
{key:"logs",checker:new api.ODCheckerBooleanStructure("opendiscord:msg-logs",{cliInitDefaultValue:true,cliDisplayName:"Logs Enabled",cliDisplayDescription:"Will this action be sent in the Discord log channel?"})}, {key:"logs",checker:new api.ODCheckerBooleanStructure("opendiscord:msg-logs",{cliInitDefaultValue:true,cliDisplayName:"Logs Enabled",cliDisplayDescription:"Will this action be sent in the Discord log channel?"})},
],cliDisplayName:displayName,cliDisplayDescription:"Configure which places this action gets logged/sent to."}) ],cliDisplayName:displayName,cliDisplayDescription:"Configure which places this action gets logged/sent to."})
} }
const createTicketEmbedStructure = (id:api.ODValidId) => {
function createPermissionStructure(id:api.ODValidId,displayName:string){
return new api.ODCheckerCustomStructure_DiscordId(id,"role",false,["admin","everyone","none"],{cliDisplayName:displayName,cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})
}
function createTicketEmbedStructure(id:api.ODValidId){
return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[ return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the embed of this message."})}, {key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the embed of this message."})},
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-text",{maxLength:256,cliDisplayName:"Title",cliDisplayDescription:"The title of this embed."})}, {key:"title",checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-text",{maxLength:256,cliDisplayName:"Title",cliDisplayDescription:"The title of this embed."})},
@@ -151,14 +168,16 @@ const createTicketEmbedStructure = (id:api.ODValidId) => {
{key:"timestamp",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-timestamp",{cliDisplayName:"Timestamp",cliDisplayDescription:"Add a timestamp to the embed."})} {key:"timestamp",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-timestamp",{cliDisplayName:"Timestamp",cliDisplayDescription:"Add a timestamp to the embed."})}
],cliDisplayName:"Message Embed",cliDisplayDescription:"Configure the embed of this message."}),cliInitDefaultValue:{enabled:false,title:"",description:"",customColor:"",image:"",thumbnail:"",fields:[],timestamp:false},cliDisplayName:"Message Embed",cliDisplayDescription:"Configure the embed of this message."}) ],cliDisplayName:"Message Embed",cliDisplayDescription:"Configure the embed of this message."}),cliInitDefaultValue:{enabled:false,title:"",description:"",customColor:"",image:"",thumbnail:"",fields:[],timestamp:false},cliDisplayName:"Message Embed",cliDisplayDescription:"Configure the embed of this message."})
} }
const createTicketPingStructure = (id:api.ODValidId) => {
function createTicketPingStructure(id:api.ODValidId){
return new api.ODCheckerObjectStructure(id,{children:[ return new api.ODCheckerObjectStructure(id,{children:[
{key:"@here",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-here",{cliDisplayName:"@here Ping",cliDisplayDescription:"Enable/disable an '@here' ping."})}, {key:"@here",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-here",{cliDisplayName:"@here Ping",cliDisplayDescription:"Enable/disable an '@here' ping."})},
{key:"@everyone",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-everyone",{cliDisplayName:"@everyone Ping",cliDisplayDescription:"Enable/disable an '@everyone' ping."})}, {key:"@everyone",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-everyone",{cliDisplayName:"@everyone Ping",cliDisplayDescription:"Enable/disable an '@everyone' ping."})},
{key:"custom",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ping-custom","role",[],{allowDoubles:false,cliDisplayPropertyName:"custom role id",cliDisplayName:"Custom Role Ping",cliDisplayDescription:"Choose your own roles to ping in this message."},{cliDisplayName:"Custom Role",cliDisplayDescription:"The discord role ID of a custom mention/ping."})}, {key:"custom",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ping-custom","role",[],{allowDoubles:false,cliDisplayPropertyName:"custom role id",cliDisplayName:"Custom Role Ping",cliDisplayDescription:"Choose your own roles to ping in this message."},{cliDisplayName:"Custom Role",cliDisplayDescription:"The discord role ID of a custom mention/ping."})},
],cliInitDefaultValue:{"@here":true,"@everyone":false,custom:[],cliDisplayName:"Message Pings",cliDisplayDescription:"Configure the pings/mentions of this message."}}) ],cliInitDefaultValue:{"@here":true,"@everyone":false,custom:[],cliDisplayName:"Message Pings",cliDisplayDescription:"Configure the pings/mentions of this message."}})
} }
const createPanelEmbedStructure = (id:api.ODValidId) => {
function createPanelEmbedStructure(id:api.ODValidId){
return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[ return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the embed of this panel."})}, {key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the embed of this panel."})},
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-text",{maxLength:256,cliDisplayName:"Title",cliDisplayDescription:"The title of this embed."})}, {key:"title",checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-text",{maxLength:256,cliDisplayName:"Title",cliDisplayDescription:"The title of this embed."})},
@@ -188,23 +207,19 @@ function loadFromEnv(){
//STRUCTURES //STRUCTURES
export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendiscord:general",{children:[ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendiscord:general",{children:[
//INFO //INFO
{key:"_INFO",cliHideInEditMode:true,checker:new api.ODCheckerObjectStructure("opendiscord:info",{children:[ {key:"_CONFIG_VERSION",cliHideInEditMode:true,checker:new api.ODCheckerStringStructure("opendiscord:config-version",{custom(checker,value,locationTrace,locationId,locationDocs) {
{key:"support",checker:new api.ODCheckerStringStructure("opendiscord:info-support",{choices:["https://otdocs.dj-dj.be"]})}, const lt = checker.locationTraceDeref(locationTrace)
{key:"discord",checker:new api.ODCheckerStringStructure("opendiscord:info-discord",{choices:["https://discord.dj-dj.be"]})},
{key:"version",checker:new api.ODCheckerStringStructure("opendiscord:info-version",{custom(checker,value,locationTrace,locationId,locationDocs) {
const lt = checker.locationTraceDeref(locationTrace)
if (typeof value != "string") return false if (typeof value != "string") return false
else if (value != "open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()){ else if (value != "open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()){
checker.createMessage("opendiscord:invalid-version","warning","The version specified in your config does not match! Make sure you have updated the config to the latest version!",lt,null,[],locationId,locationDocs) checker.createMessage("opendiscord:invalid-version","warning","The version specified in your config does not match! Make sure you have updated the config to the latest version!",lt,null,[],locationId,locationDocs)
return false return false
}else return true }else return true
},})}, },})},
]})},
//BASIC //BASIC
{key:"token",checker:(loadFromEnv()) ? new api.ODCheckerStringStructure("opendiscord:token-disabled",{cliDisplayName:"Token",cliDisplayDescription:"The token of your discord bot."}) : new api.ODCheckerCustomStructure_DiscordToken("opendiscord:token",{cliDisplayName:"Token",cliDisplayDescription:"The token of your discord bot."})}, {key:"token",checker:(loadFromEnv()) ? new api.ODCheckerStringStructure("opendiscord:token-disabled",{cliDisplayName:"Token",cliDisplayDescription:"The token of your discord bot."}) : new api.ODCheckerCustomStructure_DiscordToken("opendiscord:token",{cliDisplayName:"Token",cliDisplayDescription:"The token of your discord bot."})},
{key:"tokenFromENV",checker:new api.ODCheckerBooleanStructure("opendiscord:token-env",{cliDisplayName:"Token From ENV",cliDisplayDescription:"Use the token from the .env file instead of general.json."})}, {key:"tokenFromENV",checker:new api.ODCheckerBooleanStructure("opendiscord:token-env",{cliDisplayName:"Token From ENV",cliDisplayDescription:"Use the token from the .env file instead of general.jsonc."})},
{key:"mainColor",checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:main-color",true,false,{cliDisplayName:"Main Color",cliDisplayDescription:"The main color of your bot, used in almost all embeds."})}, {key:"mainColor",checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:main-color",true,false,{cliDisplayName:"Main Color",cliDisplayDescription:"The main color of your bot, used in almost all embeds."})},
{key:"language",checker:new api.ODCheckerStringStructure("opendiscord:language",{ {key:"language",checker:new api.ODCheckerStringStructure("opendiscord:language",{
custom:(checker,value,locationTrace,locationId,locationDocs) => { custom:(checker,value,locationTrace,locationId,locationDocs) => {
@@ -230,6 +245,7 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"status",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:status",{ {key:"status",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:status",{
property:"enabled", property:"enabled",
enabledValue:true, enabledValue:true,
ignoreCheckIfDisabled:true,
checker:new api.ODCheckerObjectStructure("opendiscord:status",{children:[ checker:new api.ODCheckerObjectStructure("opendiscord:status",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:status-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the status. When disabled, the bot will be online without any status."})}, {key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:status-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the status. When disabled, the bot will be online without any status."})},
{key:"type",checker:new api.ODCheckerStringStructure("opendiscord:status-type",{choices:["listening","watching","playing","custom"],cliDisplayName:"Type",cliDisplayDescription:"The type of status: Listening, Watching, Playing or Custom."})}, {key:"type",checker:new api.ODCheckerStringStructure("opendiscord:status-type",{choices:["listening","watching","playing","custom"],cliDisplayName:"Type",cliDisplayDescription:"The type of status: Listening, Watching, Playing or Custom."})},
@@ -241,8 +257,8 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
cliDisplayDescription:"Manage the status of the bot." cliDisplayDescription:"Manage the status of the bot."
})}, })},
//SYSTEM //TICKET SYSTEM
{key:"system",checker:new api.ODCheckerObjectStructure("opendiscord:system",{children:[ {key:"ticketSystem",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-system",{children:[
{key:"preferSlashOverText",checker:new api.ODCheckerBooleanStructure("opendiscord:prefer-slash-over-text",{cliDisplayName:"Prefer Slash Over Text",cliDisplayDescription:"Prefer displaying slash commands over text commands in help menus."})}, {key:"preferSlashOverText",checker:new api.ODCheckerBooleanStructure("opendiscord:prefer-slash-over-text",{cliDisplayName:"Prefer Slash Over Text",cliDisplayDescription:"Prefer displaying slash commands over text commands in help menus."})},
{key:"sendErrorOnUnknownCommand",checker:new api.ODCheckerBooleanStructure("opendiscord:send-error-on-unknown-command",{cliDisplayName:"Send Error On Unknown Command",cliDisplayDescription:"Send an error when using the text-command prefix without a valid command."})}, {key:"sendErrorOnUnknownCommand",checker:new api.ODCheckerBooleanStructure("opendiscord:send-error-on-unknown-command",{cliDisplayName:"Send Error On Unknown Command",cliDisplayDescription:"Send an error when using the text-command prefix without a valid command."})},
{key:"questionFieldsInCodeBlock",checker:new api.ODCheckerBooleanStructure("opendiscord:question-fields-in-code-block",{cliDisplayName:"Questions Fields In Code Blocks",cliDisplayDescription:"Display question fields in code blocks instead of plain text."})}, {key:"questionFieldsInCodeBlock",checker:new api.ODCheckerBooleanStructure("opendiscord:question-fields-in-code-block",{cliDisplayName:"Questions Fields In Code Blocks",cliDisplayDescription:"Display question fields in code blocks instead of plain text."})},
@@ -252,7 +268,8 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"useRedErrorEmbeds",checker:new api.ODCheckerBooleanStructure("opendiscord:use-red-error-embeds",{cliDisplayName:"Use Red Error Embeds",cliDisplayDescription:"Display all error messages with a red border instead of the default color of the bot."})}, {key:"useRedErrorEmbeds",checker:new api.ODCheckerBooleanStructure("opendiscord:use-red-error-embeds",{cliDisplayName:"Use Red Error Embeds",cliDisplayDescription:"Display all error messages with a red border instead of the default color of the bot."})},
{key:"alwaysShowReason",checker:new api.ODCheckerBooleanStructure("opendiscord:always-show-reason",{cliDisplayName:"Always Show Reason",cliDisplayDescription:"Always show the reason field in embeds, even when there is no reason provided."})}, {key:"alwaysShowReason",checker:new api.ODCheckerBooleanStructure("opendiscord:always-show-reason",{cliDisplayName:"Always Show Reason",cliDisplayDescription:"Always show the reason field in embeds, even when there is no reason provided."})},
{key:"emojiStyle",checker:new api.ODCheckerStringStructure("opendiscord:emoji-style",{choices:["before","after","double","disabled"],cliDisplayName:"Emoji Style",cliDisplayDescription:"Choose how the bot will display emojis in message titles. (Visit docs for more info)"})}, {key:"emojiStyle",checker:new api.ODCheckerStringStructure("opendiscord:emoji-style",{choices:["before","after","double","disabled"],cliDisplayName:"Emoji Style",cliDisplayDescription:"Choose how the bot will display emojis in message titles. (Visit docs for more info)"})},
{key:"pinEmoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:pin-emoji",1,1,false,{cliDisplayName:"Pin Emoji",cliDisplayDescription:"The emoji used when pinning tickets. This is '📌' by default."})}, {key:"pinEmoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:pin-emoji",0,1,false,{cliDisplayName:"Pin Emoji",cliDisplayDescription:"The emoji used when pinning tickets. This is '📌' by default. Leave empty to disable."})},
{key:"closeEmoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:close-emoji",0,1,false,{cliDisplayName:"Pin Emoji",cliDisplayDescription:"The emoji used when closing tickets. This is '🔒' by default. Leave empty to disable."})},
{key:"replyOnTicketCreation",checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-ticket-creation",{cliDisplayName:"Reply On Ticket Creation",cliDisplayDescription:"When enabled, the bot will send an ephemeral reply in the channel of the panel when creating a ticket."})}, {key:"replyOnTicketCreation",checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-ticket-creation",{cliDisplayName:"Reply On Ticket Creation",cliDisplayDescription:"When enabled, the bot will send an ephemeral reply in the channel of the panel when creating a ticket."})},
{key:"replyOnReactionRole",checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-reaction-role",{cliDisplayName:"Reply On Reaction Role",cliDisplayDescription:"When enabled, the bot will send an ephemeral reply in the channel of the panel when using a role button."})}, {key:"replyOnReactionRole",checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-reaction-role",{cliDisplayName:"Reply On Reaction Role",cliDisplayDescription:"When enabled, the bot will send an ephemeral reply in the channel of the panel when using a role button."})},
@@ -272,11 +289,7 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"enableTicketDeleteButtons",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-delete-buttons",{cliDisplayName:"Enable Ticket Delete Buttons",cliDisplayDescription:"Enable/disable buttons for deleting a ticket. Be aware that this doesn't disable the command!"})}, {key:"enableTicketDeleteButtons",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-delete-buttons",{cliDisplayName:"Enable Ticket Delete Buttons",cliDisplayDescription:"Enable/disable buttons for deleting a ticket. Be aware that this doesn't disable the command!"})},
{key:"enableTicketActionWithReason",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-action-with-reason",{cliDisplayName:"Enable Ticket Action With Reason",cliDisplayDescription:"Enable/disable buttons to write an additional reason for all ticket actions."})}, {key:"enableTicketActionWithReason",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-action-with-reason",{cliDisplayName:"Enable Ticket Action With Reason",cliDisplayDescription:"Enable/disable buttons to write an additional reason for all ticket actions."})},
{key:"enableDeleteWithoutTranscript",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-delete-without-transcript",{cliDisplayName:"Enable Delete Without Transcript",cliDisplayDescription:"Enable/disable the ability to delete tickets without a transcript."})}, {key:"enableDeleteWithoutTranscript",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-delete-without-transcript",{cliDisplayName:"Enable Delete Without Transcript",cliDisplayDescription:"Enable/disable the ability to delete tickets without a transcript."})},
{key:"enableCreateTicketForOtherUser",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-create-for-other-user",{cliDisplayName:"Enable Create ticket for other user",cliDisplayDescription:"Enable/disable the ability for admins to create a ticket for another user."})},
{key:"logs",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:system-logs",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:system-logs",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:logs-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable discord logs in a discord channel."})},
{key:"channel",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:logs-channel","channel",false,[],{cliDisplayName:"Log Channel",cliDisplayDescription:"The ID of the discord channel to log messages to. You can configure the messages somewhere else."})},
],cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage everything related to logs in a discord channel."}),cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage everything related to logs in a discord channel."})},
{key:"limits",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:limits",{children:[ {key:"limits",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:limits",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:limits-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable global limits."})}, {key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:limits-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable global limits."})},
@@ -287,42 +300,66 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"channelTopic",checker:new api.ODCheckerObjectStructure("opendiscord:channel-topic",{children:[ {key:"channelTopic",checker:new api.ODCheckerObjectStructure("opendiscord:channel-topic",{children:[
{key:"showOptionName",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-name",{cliDisplayName:"Show Option Name",cliDisplayDescription:"Show the option name in the channel topic."})}, {key:"showOptionName",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-name",{cliDisplayName:"Show Option Name",cliDisplayDescription:"Show the option name in the channel topic."})},
{key:"showOptionDescription",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-description",{cliDisplayName:"Show Option Description",cliDisplayDescription:"Show the option description in the channel topic."})}, {key:"showOptionDescription",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-description",{cliDisplayName:"Show Option Description",cliDisplayDescription:"Show the option description in the channel topic."})},
{key:"showOptionTopic",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-topic",{cliDisplayName:"Show Option Topic",cliDisplayDescription:"Show the option topic text in the channel topic (configured in the options.json config)."})}, {key:"showOptionTopic",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-topic",{cliDisplayName:"Show Option Topic",cliDisplayDescription:"Show the option topic text in the channel topic (configured in the options.jsonc config)."})},
{key:"showPriority",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-priority",{cliDisplayName:"Show Priority",cliDisplayDescription:"Show the current priority in the channel topic (auto-updated)."})}, {key:"showPriority",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-priority",{cliDisplayName:"Show Priority",cliDisplayDescription:"Show the current priority in the channel topic (auto-updated)."})},
{key:"showClosed",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-closed",{cliDisplayName:"Show Closed Status",cliDisplayDescription:"Show the current close/reopen status in the channel topic (auto-updated)."})}, {key:"showClosed",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-closed",{cliDisplayName:"Show Closed Status",cliDisplayDescription:"Show the current close/reopen status in the channel topic (auto-updated)."})},
{key:"showClaimed",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-claimed",{cliDisplayName:"Show Claimed Status",cliDisplayDescription:"Show the current claim status in the channel topic (auto-updated)."})}, {key:"showClaimed",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-claimed",{cliDisplayName:"Show Claimed Status",cliDisplayDescription:"Show the current claim status in the channel topic (auto-updated)."})},
{key:"showPinned",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-pinned",{cliDisplayName:"Show Pinned Status",cliDisplayDescription:"Show the current pin status in the channel topic (auto-updated)."})}, {key:"showPinned",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-pinned",{cliDisplayName:"Show Pinned Status",cliDisplayDescription:"Show the current pin status in the channel topic (auto-updated)."})},
{key:"showCreator",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-creator",{cliDisplayName:"Show Creator",cliDisplayDescription:"Show the creator of the ticket in the channel topic (auto-updated on transfer)."})}, {key:"showCreator",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-creator",{cliDisplayName:"Show Creator",cliDisplayDescription:"Show the creator of the ticket in the channel topic (auto-updated on transfer)."})},
{key:"showParticipants",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-participants",{cliDisplayName:"Show Participants",cliDisplayDescription:"Show the first 5 participants of the ticket in the channel topic (auto-updated)."})}, {key:"showParticipants",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-participants",{cliDisplayName:"Show Participants",cliDisplayDescription:"Show the first 5 participants of the ticket in the channel topic (auto-updated)."})},
],cliDisplayName:"Channel Topic",cliDisplayDescription:"Manage stats and text of ticket channel topics."})}, ],cliDisplayName:"Channel Topic",cliDisplayDescription:"Manage stats and text of ticket channel topics."})},
{key:"permissions",checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[ {key:"closedCategory",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:closed-category",{property:"enabled",enabledValue:true,ignoreCheckIfDisabled:true,checker:new api.ODCheckerObjectStructure("opendiscord:closed-category",{children:[
{key:"help",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-help","role",false,["admin","everyone","none"],{cliDisplayName:"Help",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})}, {key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:closed-category-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable closed category."})},
{key:"panel",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-panel","role",false,["admin","everyone","none"],{cliDisplayName:"Panel",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})}, {key:"categoryId",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:closed-category","category",true,[],{cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where tickets will be moved to when closed."})},
{key:"ticket",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-ticket","role",false,["admin","everyone","none"],{cliDisplayName:"Ticket",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})}, ],cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where tickets will be moved to when closed."}),cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where tickets will be moved to when closed."})},
{key:"close",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-close","role",false,["admin","everyone","none"],{cliDisplayName:"Close",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"delete",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-delete","role",false,["admin","everyone","none"],{cliDisplayName:"Delete",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"reopen",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-reopen","role",false,["admin","everyone","none"],{cliDisplayName:"Reopen",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"claim",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-claim","role",false,["admin","everyone","none"],{cliDisplayName:"Claim",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"unclaim",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unclaim","role",false,["admin","everyone","none"],{cliDisplayName:"Unclaim",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"pin",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-pin","role",false,["admin","everyone","none"],{cliDisplayName:"Pin",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"unpin",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unpin","role",false,["admin","everyone","none"],{cliDisplayName:"Unpin",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"move",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-move","role",false,["admin","everyone","none"],{cliDisplayName:"Move",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"rename",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-rename","role",false,["admin","everyone","none"],{cliDisplayName:"Rename",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"add",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-add","role",false,["admin","everyone","none"],{cliDisplayName:"Add User",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"remove",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-remove","role",false,["admin","everyone","none"],{cliDisplayName:"Remove User",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"blacklist",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-blacklist","role",false,["admin","everyone","none"],{cliDisplayName:"Blacklist",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"stats",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-stats","role",false,["admin","everyone","none"],{cliDisplayName:"Stats",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"clear",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-clear","role",false,["admin","everyone","none"],{cliDisplayName:"Clear Tickets",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"autoclose",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autoclose","role",false,["admin","everyone","none"],{cliDisplayName:"Autoclose",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"autodelete",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autodelete","role",false,["admin","everyone","none"],{cliDisplayName:"Autodelete",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"transfer",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-transfer","role",false,["admin","everyone","none"],{cliDisplayName:"Transfer",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"topic",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-topic","role",false,["admin","everyone","none"],{cliDisplayName:"Topic",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"priority",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-priority","role",false,["admin","everyone","none"],{cliDisplayName:"Priority",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
],cliDisplayName:"Permissions",cliDisplayDescription:"Manage all button & command permissions in the bot. (Visit docs for more info)"})},
{key:"messages",checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[ {key:"backupCategory",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:backup-category",{property:"enabled",enabledValue:true,ignoreCheckIfDisabled:true,checker:new api.ODCheckerObjectStructure("opendiscord:backup-category",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:backup-category-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable backup category."})},
{key:"categoryId",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:backup-category","category",true,[],{cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where tickets will be created in when the original category is full (50 channels)."})},
],cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where tickets will be created in when the original category is full (50 channels)."}),cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where tickets will be created in when the original category is full (50 channels)."})},
{key:"claimedCategories",checker:new api.ODCheckerArrayStructure("opendiscord:claimed-categories",{allowDoubles:false,allowedTypes:["object"],cliDisplayPropertyName:"claim category",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:claimed-category",{children:[
{key:"user",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:claimed-user","user",false,[],{cliDisplayName:"User",cliDisplayDescription:"The discord user ID of a ticket claimer."})},
{key:"category",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:claimed-category","category",false,[],{cliDisplayName:"Category",cliDisplayDescription:"The discord category ID to move the ticket to."})}
],cliDisplayName:"Claimed Category",cliDisplayDescription:"Move claimed tickets to the matching channel category of the user that claimed the ticket."}),cliDisplayName:"Claimed Categories",cliDisplayDescription:"Move claimed tickets to the matching channel category of the user that claimed the ticket."})},
],cliDisplayName:"Ticket System",cliDisplayDescription:"Configure the 'Open Ticket' ticket system."})},
//COMMAND PERMISSIONS
{key:"permissions",checker:new api.ODCheckerObjectStructure("opendiscord:permissions",{children:[
{key:"help",checker:createPermissionStructure("opendiscord:permissions-help","Help")},
{key:"panel",checker:createPermissionStructure("opendiscord:permissions-panel","Panel")},
{key:"ticket",checker:createPermissionStructure("opendiscord:permissions-ticket","Ticket")},
{key:"close",checker:createPermissionStructure("opendiscord:permissions-close","Close")},
{key:"delete",checker:createPermissionStructure("opendiscord:permissions-delete","Delete")},
{key:"reopen",checker:createPermissionStructure("opendiscord:permissions-reopen","Reopen")},
{key:"claim",checker:createPermissionStructure("opendiscord:permissions-claim","Claim")},
{key:"unclaim",checker:createPermissionStructure("opendiscord:permissions-unclaim","Unclaim")},
{key:"pin",checker:createPermissionStructure("opendiscord:permissions-pin","Pin")},
{key:"unpin",checker:createPermissionStructure("opendiscord:permissions-unpin","Unpin")},
{key:"move",checker:createPermissionStructure("opendiscord:permissions-move","Move")},
{key:"rename",checker:createPermissionStructure("opendiscord:permissions-rename","Rename")},
{key:"add",checker:createPermissionStructure("opendiscord:permissions-add","Add User")},
{key:"remove",checker:createPermissionStructure("opendiscord:permissions-remove","Remove User")},
{key:"blacklist",checker:createPermissionStructure("opendiscord:permissions-blacklist","Blacklist")},
{key:"stats",checker:createPermissionStructure("opendiscord:permissions-stats","Stats")},
{key:"clear",checker:createPermissionStructure("opendiscord:permissions-clear","Clear Tickets")},
{key:"autoclose",checker:createPermissionStructure("opendiscord:permissions-autoclose","Autoclose")},
{key:"autodelete",checker:createPermissionStructure("opendiscord:permissions-autodelete","Autodelete")},
{key:"transfer",checker:createPermissionStructure("opendiscord:permissions-transfer","Transfer")},
{key:"topic",checker:createPermissionStructure("opendiscord:permissions-topic","Topic")},
{key:"priority",checker:createPermissionStructure("opendiscord:permissions-priority","Priority")},
{key:"transcripts",checker:createPermissionStructure("opendiscord:permissions-transcripts","Transcripts History")},
],cliDisplayName:"Permissions",cliDisplayDescription:"Manage all button & command permissions in the bot. (Visit docs for more info)"})},
//LOGS
{key:"logs",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:logs",{property:"enabled",enabledValue:true,ignoreCheckIfDisabled:true,checker:new api.ODCheckerObjectStructure("opendiscord:logs",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:logs-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable discord logs in a discord channel."})},
{key:"channel",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:logs-channel","channel",false,[],{cliDisplayName:"Log Channel",cliDisplayDescription:"The log message channel ID."})},
//LOG MESSAGES
{key:"logMessages",checker:new api.ODCheckerObjectStructure("opendiscord:log-messages",{children:[
{key:"creation",checker:createMsgStructure("opendiscord:msg-creation","Ticket Created")}, {key:"creation",checker:createMsgStructure("opendiscord:msg-creation","Ticket Created")},
{key:"closing",checker:createMsgStructure("opendiscord:msg-closing","Ticket Closed")}, {key:"closing",checker:createMsgStructure("opendiscord:msg-closing","Ticket Closed")},
{key:"deleting",checker:createMsgStructure("opendiscord:msg-deleting","Ticket Deleted")}, {key:"deleting",checker:createMsgStructure("opendiscord:msg-deleting","Ticket Deleted")},
@@ -338,22 +375,23 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"topicChange",checker:createMsgStructure("opendiscord:msg-topic-change","Topic Changed")}, {key:"topicChange",checker:createMsgStructure("opendiscord:msg-topic-change","Topic Changed")},
{key:"priorityChange",checker:createMsgStructure("opendiscord:msg-priority-change","Priority Changed")}, {key:"priorityChange",checker:createMsgStructure("opendiscord:msg-priority-change","Priority Changed")},
{key:"reactionRole",checker:createMsgStructure("opendiscord:msg-reaction-role","Reaction Role")}, {key:"reactionRole",checker:createMsgStructure("opendiscord:msg-reaction-role","Reaction Role")},
],cliDisplayName:"Messages",cliDisplayDescription:"Manage all messages & DM's for each action of the bot. (Visit docs for more info)"})}, ],cliDisplayName:"Log Messages",cliDisplayDescription:"Manage all messages & DM's for each action of the bot. (Visit docs for more info)"})},
],cliDisplayName:"System",cliDisplayDescription:"Configure everything related to the ticket system."})} ],cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage the 'Open Ticket' logs channel."}),cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage the 'Open Ticket' logs channel."})},
],cliDisplayName:"General",cliDisplayDescription:"General settings for the bot."}) ],cliDisplayName:"General",cliDisplayDescription:"General settings for the bot."})
export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendiscord:options",{allowedTypes:["object"],cliDisplayPropertyName:"option",propertyChecker:new api.ODCheckerObjectSwitchStructure("opendiscord:options",{objects:[ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendiscord:options",{allowedTypes:["object"],cliDisplayPropertyName:"option",propertyChecker:new api.ODCheckerObjectSwitchStructure("opendiscord:options",{objects:[
//TICKET //TICKET
{name:"Ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("opendiscord:ticket",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],cliInitSkipKeys:["readonlyAdmins"],children:[ {name:"Ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("opendiscord:ticket",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],cliInitSkipKeys:["readonlyAdmins"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:ticket-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this ticket option. Used in panels."})}, {key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this ticket option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:ticket-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this ticket option."})}, {key:"name",checker:new api.ODCheckerStringStructure("opendiscord:name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this ticket option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:ticket-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this ticket option."})}, {key:"description",checker:new api.ODCheckerStringStructure("opendiscord:description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this ticket option."})},
//TICKET BUTTON //TICKET BUTTON
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[ {key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})}, {key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})}, {key:"label",checker:new api.ODCheckerStringStructure("opendiscord:button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"color",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})}, {key:"color",checker:new api.ODCheckerStringStructure("opendiscord:button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
],custom:(checker,value,locationTrace,locationId,locationDocs) => { ],custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace) const lt = checker.locationTraceDeref(locationTrace)
//check if emoji & label exists //check if emoji & label exists
@@ -369,7 +407,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
{key:"ticketAdmins",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ticket-admins","role",[],{allowDoubles:false,cliDisplayPropertyName:"ticket admin role",cliDisplayName:"Ticket Admin Roles",cliDisplayDescription:"A list of role IDs that are only able to interact with this ticket option."},{cliDisplayName:"Ticket Admin Role",cliDisplayDescription:"The discord role ID of a ticket admin."})}, {key:"ticketAdmins",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ticket-admins","role",[],{allowDoubles:false,cliDisplayPropertyName:"ticket admin role",cliDisplayName:"Ticket Admin Roles",cliDisplayDescription:"A list of role IDs that are only able to interact with this ticket option."},{cliDisplayName:"Ticket Admin Role",cliDisplayDescription:"The discord role ID of a ticket admin."})},
{key:"readonlyAdmins",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-readonly-admins","role",[],{allowDoubles:false,cliInitDefaultValue:[],cliDisplayPropertyName:"read-only ticket admin role",cliDisplayName:"Readonly Admin Roles",cliDisplayDescription:"A list of role IDs that are only able to read this ticket option."},{cliDisplayName:"Readonly Admin Role",cliDisplayDescription:"The discord role ID of a readonly admin."})}, {key:"readonlyAdmins",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-readonly-admins","role",[],{allowDoubles:false,cliInitDefaultValue:[],cliDisplayPropertyName:"read-only ticket admin role",cliDisplayName:"Readonly Admin Roles",cliDisplayDescription:"A list of role IDs that are only able to read this ticket option."},{cliDisplayName:"Readonly Admin Role",cliDisplayDescription:"The discord role ID of a readonly admin."})},
{key:"allowCreationByBlacklistedUsers",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-allow-blacklisted-users",{cliDisplayName:"Allow Creation By Blacklisted Users",cliDisplayDescription:"When enabled, the blacklist doesn't apply to this ticket option/type and users are still able to create a ticket."})}, {key:"allowCreationByBlacklistedUsers",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-allow-blacklisted-users",{cliDisplayName:"Allow Creation By Blacklisted Users",cliDisplayDescription:"When enabled, the blacklist doesn't apply to this ticket option/type and users are still able to create a ticket."})},
{key:"questions",checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5,cliDisplayPropertyName:"question",cliDisplayName:"Questions",cliDisplayDescription:"A list of valid question IDs to ask before creating this ticket."},{cliDisplayName:"Question ID",cliDisplayDescription:"A valid question ID from the questions.json config.",cliAutocompleteFunc:async () => { {key:"questions",checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5,cliDisplayPropertyName:"question",cliDisplayName:"Questions",cliDisplayDescription:"A list of valid question IDs to ask before creating this ticket."},{cliDisplayName:"Question ID",cliDisplayDescription:"A valid question ID from the questions.jsonc config.",cliAutocompleteFunc:async () => {
const uncheckedRawData = opendiscord.configs.get("opendiscord:questions").data const uncheckedRawData = opendiscord.configs.get("opendiscord:questions").data
if (!Array.isArray(uncheckedRawData)) return null if (!Array.isArray(uncheckedRawData)) return null
const idList = uncheckedRawData.filter((option) => typeof option == "object" && typeof option["id"] == "string").map((option) => option.id) const idList = uncheckedRawData.filter((option) => typeof option == "object" && typeof option["id"] == "string").map((option) => option.id)
@@ -380,15 +418,8 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
{key:"channel",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel",{cliInitSkipKeys:["backupCategory","claimedCategory"],children:[ {key:"channel",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel",{cliInitSkipKeys:["backupCategory","claimedCategory"],children:[
{key:"prefix",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-prefix",{maxLength:25,regex:/^[^\s]*$/,cliDisplayName:"Prefix",cliDisplayDescription:"The prefix of the name of the ticket channel. (e.g. 'question-')"})}, {key:"prefix",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-prefix",{maxLength:25,regex:/^[^\s]*$/,cliDisplayName:"Prefix",cliDisplayDescription:"The prefix of the name of the ticket channel. (e.g. 'question-')"})},
{key:"suffix",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-suffix",{choices:["user-name","user-nickname","user-id","random-number","random-hex","counter-dynamic","counter-fixed"],cliDisplayName:"Suffix",cliDisplayDescription:"The suffix mode to use. The number/text will be appended after the prefix."})}, {key:"suffix",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-suffix",{choices:["user-name","user-nickname","user-id","random-number","random-hex","counter-dynamic","counter-fixed"],cliDisplayName:"Suffix",cliDisplayDescription:"The suffix mode to use. The number/text will be appended after the prefix."})},
{key:"category",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-category","category",true,[],{cliDisplayName:"Category",cliDisplayDescription:"The category the ticket will be created in. Leave empty for no category."})}, {key:"category",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-category","category",true,[],{cliDisplayName:"Category",cliDisplayDescription:"The category the ticket will be created in. Leave empty for no category."})},
{key:"closedCategory",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-closed-category","category",true,[],{cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where the ticket will be moved to when closed."})}, {key:"topic",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-topic",{cliDisplayName:"Channel Topic",cliDisplayDescription:"The topic text of the ticket channel. Visible in the discord client when general.jsonc 'channelTopic'.'showOptionTopic' is enabled."})},
{key:"backupCategory",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-backup-category","category",true,[],{cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where the ticket will be created in when the primary category is full (50 channels)."})},
{key:"claimedCategory",checker:new api.ODCheckerArrayStructure("opendiscord:ticket-channel-claimed-category",{allowDoubles:false,allowedTypes:["object"],cliDisplayPropertyName:"claim category",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel-claimed-category",{children:[
{key:"user",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-user","user",false,[],{cliDisplayName:"User",cliDisplayDescription:"A discord user ID of the ticket claimer."})},
{key:"category",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-category","category",false,[],{cliDisplayName:"Category",cliDisplayDescription:"A discord category ID to move the ticket to."})}
],cliDisplayName:"Claimed Category",cliDisplayDescription:"A collection of a user ID and a category ID. The ticket will be moved to the category when this user claims the ticket."}),cliDisplayName:"Claimed Categories",cliDisplayDescription:"Add categories to move the ticket to when a user claims a ticket."})},
{key:"topic",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-topic",{cliDisplayName:"Channel Topic",cliDisplayDescription:"The topic text of the ticket channel. Visible in the discord client when general.json 'channelTopic'.'showOptionTopic' is enabled."})},
],cliDisplayName:"Channel",cliDisplayDescription:"Manage all settings related to the ticket channel and categories."})}, ],cliDisplayName:"Channel",cliDisplayDescription:"Manage all settings related to the ticket channel and categories."})},
//DM MESSAGE //DM MESSAGE
@@ -445,14 +476,14 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
//WEBSITE //WEBSITE
{name:"Website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("opendiscord:website",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[ {name:"Website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("opendiscord:website",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:website-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this website option. Used in panels."})}, {key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this website option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:website-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this website option."})}, {key:"name",checker:new api.ODCheckerStringStructure("opendiscord:name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this website option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:website-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this website option."})}, {key:"description",checker:new api.ODCheckerStringStructure("opendiscord:description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this website option."})},
//WEBSITE BUTTON //WEBSITE BUTTON
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[ {key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})}, {key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})}, {key:"label",checker:new api.ODCheckerStringStructure("opendiscord:button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
],custom:(checker,value,locationTrace,locationId,locationDocs) => { ],custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace) const lt = checker.locationTraceDeref(locationTrace)
//check if emoji & label exists //check if emoji & label exists
@@ -470,15 +501,15 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
//REACTION ROLES //REACTION ROLES
{name:"Reaction Role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("opendiscord:role",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[ {name:"Reaction Role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("opendiscord:role",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:role-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this role option. Used in panels."})}, {key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this role option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:role-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this role option."})}, {key:"name",checker:new api.ODCheckerStringStructure("opendiscord:name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this role option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:role-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this role option."})}, {key:"description",checker:new api.ODCheckerStringStructure("opendiscord:description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this role option."})},
//ROLE BUTTON //ROLE BUTTON
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[ {key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})}, {key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})}, {key:"label",checker:new api.ODCheckerStringStructure("opendiscord:button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"color",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})}, {key:"color",checker:new api.ODCheckerStringStructure("opendiscord:button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
],custom:(checker,value,locationTrace,locationId,locationDocs) => { ],custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace) const lt = checker.locationTraceDeref(locationTrace)
//check if emoji & label exists //check if emoji & label exists
@@ -496,13 +527,52 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
{key:"removeRolesOnAdd",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-remove-roles","role",[],{allowDoubles:false,cliDisplayPropertyName:"role",cliDisplayName:"Remove Roles On Add",cliDisplayDescription:"An additional list of roles to remove when the roles of this option are added. (Can be used to select between roles)"},{cliDisplayName:"Remove Role",cliDisplayDescription:"The discord role ID you want to remove when other roles are added."})}, {key:"removeRolesOnAdd",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-remove-roles","role",[],{allowDoubles:false,cliDisplayPropertyName:"role",cliDisplayName:"Remove Roles On Add",cliDisplayDescription:"An additional list of roles to remove when the roles of this option are added. (Can be used to select between roles)"},{cliDisplayName:"Remove Role",cliDisplayDescription:"The discord role ID you want to remove when other roles are added."})},
{key:"addOnMemberJoin",checker:new api.ODCheckerBooleanStructure("opendiscord:role-add-on-join",{cliDisplayName:"Add On Member Join",cliDisplayDescription:"Automatically add these roles to a user when joining the server."})}, {key:"addOnMemberJoin",checker:new api.ODCheckerBooleanStructure("opendiscord:role-add-on-join",{cliDisplayName:"Add On Member Join",cliDisplayDescription:"Automatically add these roles to a user when joining the server."})},
],cliDisplayName:"Reaction Role Option",cliDisplayDescription:"Manage all settings of this reaction role option."})}, ],cliDisplayName:"Reaction Role Option",cliDisplayDescription:"Manage all settings of this reaction role option."})},
//SUB-PANEL
{name:"Reaction Role",priority:0,properties:[{key:"type",value:"sub-panel"}],checker:new api.ODCheckerObjectStructure("opendiscord:sub-panel",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this sub-panel option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this sub-panel option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this sub-panel option."})},
//SUB-PANEL BUTTON
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"color",checker:new api.ODCheckerStringStructure("opendiscord:button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace)
//check if emoji & label exists
if (typeof value != "object") return false
else if (value && value["emoji"].length < 1 && value["label"].length < 1){
//label & emoji are both empty
checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs)
return false
}else return true
},cliDisplayName:"Button",cliDisplayDescription:"Customise the button layout of this sub-panel option."})},
//SUB-PANEL SETTINGS
{key:"subPanelId",checker:new api.ODCheckerStringStructure("ot-footers:panel-id",{custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace)
if (typeof value != "string") return false
if (getUnsafePanelIds().includes(value)){
//exists
return true
}else{
//doesn't exist
checker.createMessage("opendiscord:id-non-existent","error",`The panel id "${value}" doesn't exist!`,lt,null,[`"${value}"`],locationId,locationDocs)
return false
}
}})},
],cliDisplayName:"Sub-Panel Option",cliDisplayDescription:"Manage all settings of this sub-panel option."})},
],cliDisplayName:"Option",cliDisplayDescription:"Manage an option of one of the 3 types: ticket, website, role."}),cliDisplayName:"Options",cliDisplayDescription:"A list of all options in the bot. Here you can add, modify & remove ticket types, website buttons & reaction roles!"}) ],cliDisplayName:"Option",cliDisplayDescription:"Manage an option of one of the 3 types: ticket, website, role."}),cliDisplayName:"Options",cliDisplayDescription:"A list of all options in the bot. Here you can add, modify & remove ticket types, website buttons & reaction roles!"})
export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendiscord:panels",{allowedTypes:["object"],cliDisplayPropertyName:"panel",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panels",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","dropdown"],children:[ export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendiscord:panels",{allowedTypes:["object"],cliDisplayPropertyName:"panel",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panels",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","dropdown"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:panel-id","openticket","panel-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this panel. Used in the /panel command."})}, {key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:panel-id","openticket","panel-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this panel. Used in the /panel command."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:panel-name",{minLength:3,maxLength:50,cliDisplayName:"Name",cliDisplayDescription:"The name of this panel."})}, {key:"name",checker:new api.ODCheckerStringStructure("opendiscord:panel-name",{minLength:3,maxLength:50,cliDisplayName:"Name",cliDisplayDescription:"The name of this panel."})},
{key:"dropdown",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-dropdown",{cliDisplayName:"Dropdown",cliDisplayDescription:"Decide whether to use buttons or a dropdown in the panel. Dropdowns only support options of the 'ticket' type!"})}, {key:"dropdown",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-dropdown",{cliDisplayName:"Dropdown",cliDisplayDescription:"Decide whether to use buttons or a dropdown in the panel. Dropdowns only support options of the 'ticket' type!"})},
{key:"options",checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,minLength:1,maxLength:25,cliDisplayPropertyName:"option",cliDisplayName:"Options",cliDisplayDescription:"A list of valid option IDs to show in this panel."},{cliDisplayName:"Option ID",cliDisplayDescription:"A valid option ID from the options.json config.",cliAutocompleteFunc:async () => { {key:"options",checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,minLength:1,maxLength:25,cliDisplayPropertyName:"option",cliDisplayName:"Options",cliDisplayDescription:"A list of valid option IDs to show in this panel."},{cliDisplayName:"Option ID",cliDisplayDescription:"A valid option ID from the options.jsonc config.",cliAutocompleteFunc:async () => {
const uncheckedRawData = opendiscord.configs.get("opendiscord:options").data const uncheckedRawData = opendiscord.configs.get("opendiscord:options").data
if (!Array.isArray(uncheckedRawData)) return null if (!Array.isArray(uncheckedRawData)) return null
const idList = uncheckedRawData.filter((option) => typeof option == "object" && typeof option["id"] == "string").map((option) => option.id) const idList = uncheckedRawData.filter((option) => typeof option == "object" && typeof option["id"] == "string").map((option) => option.id)
@@ -516,6 +586,8 @@ export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendisco
//SETTINGS //SETTINGS
{key:"settings",checker:new api.ODCheckerObjectStructure("opendiscord:panel-settings",{cliInitSkipKeys:["dropdownPlaceholder","describeOptionsCustomTitle"],children:[ {key:"settings",checker:new api.ODCheckerObjectStructure("opendiscord:panel-settings",{cliInitSkipKeys:["dropdownPlaceholder","describeOptionsCustomTitle"],children:[
{key:"dropdownPlaceholder",checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-placeholder",{maxLength:100,cliInitDefaultValue:"Create a ticket!",cliDisplayName:"Dropdown Placeholder",cliDisplayDescription:"Configure the text displayed in the dropdown when nothing is selected."})}, {key:"dropdownPlaceholder",checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-placeholder",{maxLength:100,cliInitDefaultValue:"Create a ticket!",cliDisplayName:"Dropdown Placeholder",cliDisplayDescription:"Configure the text displayed in the dropdown when nothing is selected."})},
{key:"maximumButtonsPerRow",checker:new api.ODCheckerNumberStructure("opendiscord:panel-settings-row-amount",{min:1,max:5,floatAllowed:false,cliInitDefaultValue:5,cliDisplayName:"Maximum Buttons Per Row",cliDisplayDescription:"Set the maximum amount of buttons in a single row before starting a new one."})},
{key:"enableMaxTicketsWarningInText",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-text",{cliDisplayName:"Enable Max Tickets Warning (Text)",cliDisplayDescription:"Enable/disable the warning which shows how many tickets you can create in the text contents of the panel."})}, {key:"enableMaxTicketsWarningInText",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-text",{cliDisplayName:"Enable Max Tickets Warning (Text)",cliDisplayDescription:"Enable/disable the warning which shows how many tickets you can create in the text contents of the panel."})},
{key:"enableMaxTicketsWarningInEmbed",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-embed",{cliDisplayName:"Enable Max Tickets Warning (Embed)",cliDisplayDescription:"Enable/disable the warning which shows how many tickets you can create in the embed of the panel."})}, {key:"enableMaxTicketsWarningInEmbed",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-embed",{cliDisplayName:"Enable Max Tickets Warning (Embed)",cliDisplayDescription:"Enable/disable the warning which shows how many tickets you can create in the embed of the panel."})},
@@ -527,20 +599,95 @@ export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendisco
],cliDisplayName:"Settings",cliDisplayDescription:"Manage additional settings & customisability for this panel."})}, ],cliDisplayName:"Settings",cliDisplayDescription:"Manage additional settings & customisability for this panel."})},
],cliDisplayName:"Panel",cliDisplayDescription:"Manage, customise and configure a panel to your preference."}),cliDisplayName:"Panels",cliDisplayDescription:"A list of all panels in the bot. Here you can add, modify & remove existing panels or customise them to your preference."}) ],cliDisplayName:"Panel",cliDisplayDescription:"Manage, customise and configure a panel to your preference."}),cliDisplayName:"Panels",cliDisplayDescription:"A list of all panels in the bot. Here you can add, modify & remove existing panels or customise them to your preference."})
export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("opendiscord:questions",{allowedTypes:["object"],cliDisplayPropertyName:"question",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:questions",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[ export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("opendiscord:questions",{allowedTypes:["object"],cliDisplayPropertyName:"question",propertyChecker:new api.ODCheckerObjectSwitchStructure("opendiscord:options",{objects:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})}, //SHORT QUESTION
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})}, {name:"Short Question",priority:0,properties:[{key:"type",value:"short"}],checker:new api.ODCheckerObjectStructure("opendiscord:short-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"type",checker:new api.ODCheckerStringStructure("opendiscord:question-type",{choices:["short","paragraph"],cliDisplayName:"Type",cliDisplayDescription:"The type of this question (short/paragraph)."})}, {key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})}, {key:"placeholder",checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
{key:"placeholder",checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
{key:"length",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[ {key:"length",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:question-length-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable length validation for this question."})}, {key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:question-length-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable length validation for this question."})},
{key:"min",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false,cliDisplayName:"Min Length",cliDisplayDescription:"The minimum amount of characters required."})}, {key:"min",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false,cliDisplayName:"Min Length",cliDisplayDescription:"The minimum amount of characters required."})},
{key:"max",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false,cliInitDefaultValue:100,cliDisplayName:"Max Length",cliDisplayDescription:"The maximum amount of characters allowed."})}, {key:"max",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false,cliInitDefaultValue:100,cliDisplayName:"Max Length",cliDisplayDescription:"The maximum amount of characters allowed."})},
],cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."}),cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."})}, ],cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."}),cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."})},
],cliDisplayName:"Question",cliDisplayDescription:"Manage, customise and configure a question to your preference."}),cliDisplayName:"Questions",cliDisplayDescription:"A list of all questions in the bot. Here you can add, modify & remove existing questions or customise them to your preference."}) ],cliDisplayName:"Short Question",cliDisplayDescription:"Manage, customise and configure the short question to your preference."})},
//PARAGRAPH QUESTION
{name:"Paragraph Question",priority:0,properties:[{key:"type",value:"paragraph"}],checker:new api.ODCheckerObjectStructure("opendiscord:paragraph-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"placeholder",checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
{key:"length",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:question-length-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable length validation for this question."})},
{key:"min",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false,cliDisplayName:"Min Length",cliDisplayDescription:"The minimum amount of characters required."})},
{key:"max",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false,cliInitDefaultValue:100,cliDisplayName:"Max Length",cliDisplayDescription:"The maximum amount of characters allowed."})},
],cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."}),cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."})},
],cliDisplayName:"Paragraph Question",cliDisplayDescription:"Manage, customise and configure the paragraph question to your preference."})},
//TEXT DISPLAY QUESTION
{name:"Text Display Question",priority:0,properties:[{key:"type",value:"text-display"}],checker:new api.ODCheckerObjectStructure("opendiscord:text-display-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this text display. Used in ticket options."})},
{key:"textContents",checker:new api.ODCheckerStringStructure("opendiscord:text-contents",{minLength:1,maxLength:2048,cliDisplayName:"Text Contents",cliDisplayDescription:"The text contents to show in the modal."})},
],cliDisplayName:"Text Display Question",cliDisplayDescription:"Manage, customise and configure the text display question to your preference."})},
//DROPDOWN QUESTION
{name:"Dropdown Question",priority:0,properties:[{key:"type",value:"dropdown"}],checker:new api.ODCheckerObjectStructure("opendiscord:dropdown-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"placeholder",checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
{key:"choices",checker:new api.ODCheckerArrayStructure("opendiscord:choices",{allowedTypes:["object"],minLength:1,maxLength:25,propertyChecker:new api.ODCheckerObjectStructure("opendiscord:choice",{children:[
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:choice-title",{minLength:1,maxLength:100,cliDisplayName:"Title",cliDisplayDescription:"The title of this choice."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:choice-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this choice."})},
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:choice-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the choice. Leave empty to disable."})}
],cliDisplayName:"Choice",cliDisplayDescription:"A choice for this dropdown question."}),cliDisplayName:"Choices",cliDisplayPropertyName:"choice",cliDisplayDescription:"Manage all available choices of this dropdown question."})}
],cliDisplayName:"Dropdown Question",cliDisplayDescription:"Manage, customise and configure the dropdown question to your preference."})},
//RADIO SELECT QUESTION
{name:"Radio Select Question",priority:0,properties:[{key:"type",value:"radio-select"}],checker:new api.ODCheckerObjectStructure("opendiscord:radio-select-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"choices",checker:new api.ODCheckerArrayStructure("opendiscord:choices",{allowedTypes:["object"],minLength:2,maxLength:10,propertyChecker:new api.ODCheckerObjectStructure("opendiscord:choice",{children:[
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:choice-title",{minLength:1,maxLength:100,cliDisplayName:"Title",cliDisplayDescription:"The title of this choice."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:choice-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this choice."})},
{key:"selectedByDefault",checker:new api.ODCheckerBooleanStructure("opendiscord:choice-default",{cliDisplayName:"Selected By Default",cliDisplayDescription:"Should this choice be selected by default?"})}
],cliDisplayName:"Choice",cliDisplayDescription:"A choice for this radio select question."}),cliDisplayName:"Choices",cliDisplayPropertyName:"choice",cliDisplayDescription:"Manage all available choices of this radio select question."})}
],cliDisplayName:"Radio Select Question",cliDisplayDescription:"Manage, customise and configure the radio select question to your preference."})},
//CHECKBOX SELECT QUESTION
{name:"Checkbox Select Question",priority:0,properties:[{key:"type",value:"checkbox-select"}],checker:new api.ODCheckerObjectStructure("opendiscord:checkbox-select-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"limits",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:amount",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:amount",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:amount-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable checking the min/max amount of required checkboxes."})},
{key:"min",checker:new api.ODCheckerNumberStructure("opendiscord:amount-min",{min:0,max:10,floatAllowed:false,cliDisplayName:"Min Amount",cliDisplayDescription:"The minimum amount of checkboxes required."})},
{key:"max",checker:new api.ODCheckerNumberStructure("opendiscord:amount-max",{min:1,max:10,floatAllowed:false,cliInitDefaultValue:10,cliDisplayName:"Max Amount",cliDisplayDescription:"The maximum amount of checkboxes allowed."})},
],cliDisplayName:"Checkbox Limits",cliDisplayDescription:"Verify the minimum or maximum amount of checkboxes required."}),cliDisplayName:"Checkbox Limits",cliDisplayDescription:"Verify the minimum or maximum amount of checkboxes required."})},
{key:"choices",checker:new api.ODCheckerArrayStructure("opendiscord:choices",{allowedTypes:["object"],minLength:1,maxLength:10,propertyChecker:new api.ODCheckerObjectStructure("opendiscord:choice",{children:[
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:choice-title",{minLength:1,maxLength:100,cliDisplayName:"Title",cliDisplayDescription:"The title of this choice."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:choice-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this choice."})},
{key:"selectedByDefault",checker:new api.ODCheckerBooleanStructure("opendiscord:choice-default",{cliDisplayName:"Selected By Default",cliDisplayDescription:"Should this choice be selected by default?"})}
],cliDisplayName:"Choice",cliDisplayDescription:"A choice for this checkbox select question."}),cliDisplayName:"Choices",cliDisplayPropertyName:"choice",cliDisplayDescription:"Manage all available choices of this checkbox select question."})}
],cliDisplayName:"Checkbox Select Question",cliDisplayDescription:"Manage, customise and configure the checkbox select question to your preference."})},
],cliDisplayName:"Question",cliDisplayDescription:"Manage a question of one of the 6 types: short, paragraph, text-display, dropdown, radio-select, checkbox-select."}),cliDisplayName:"Questions",cliDisplayDescription:"A list of all questions in the bot. Here you can add, modify & remove existing questions or customise them to your preference."})
export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("opendiscord:transcripts",{children:[ export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("opendiscord:transcripts",{children:[
//GENERAL //GENERAL
+3 -3
View File
@@ -30,7 +30,7 @@ export async function loadCommandErrorHandlingCode(){
error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message)
}else if (error.type == "missing_option"){ }else if (error.type == "missing_option"){
error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-option-missing").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-option-missing").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message)
}else if (error.type == "unknown_command" && generalConfig.data.system.sendErrorOnUnknownCommand){ }else if (error.type == "unknown_command" && generalConfig.data.ticketSystem.sendErrorOnUnknownCommand){
error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-unknown-command").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-unknown-command").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message)
} }
}) })
@@ -459,7 +459,7 @@ const loadAutoCode = () => {
if (lastMessage){ if (lastMessage){
//ticket has last message //ticket has last message
const disableOnClaim = ticket.option.get("opendiscord:autodelete-disable-claim").value && ticket.get("opendiscord:claimed").value const disableOnClaim = ticket.option.get("opendiscord:autodelete-disable-claim").value && ticket.get("opendiscord:claimed").value
const disableWhenNotClosed = generalConfig.data.system.autodeleteRequiresClosedTicket && !ticket.get("opendiscord:closed").value const disableWhenNotClosed = generalConfig.data.ticketSystem.autodeleteRequiresClosedTicket && !ticket.get("opendiscord:closed").value
const enabled = (disableOnClaim || disableWhenNotClosed) ? false : ticket.get("opendiscord:autodelete-enabled").value const enabled = (disableOnClaim || disableWhenNotClosed) ? false : ticket.get("opendiscord:autodelete-enabled").value
const days = ticket.get("opendiscord:autodelete-days").value const days = ticket.get("opendiscord:autodelete-days").value
@@ -490,7 +490,7 @@ const loadAutoCode = () => {
if (!channel) return if (!channel) return
//ticket has been created by this user //ticket has been created by this user
const disableOnClaim = ticket.option.get("opendiscord:autodelete-disable-claim").value && ticket.get("opendiscord:claimed").value const disableOnClaim = ticket.option.get("opendiscord:autodelete-disable-claim").value && ticket.get("opendiscord:claimed").value
const disableWhenNotClosed = generalConfig.data.system.autodeleteRequiresClosedTicket && !ticket.get("opendiscord:closed").value const disableWhenNotClosed = generalConfig.data.ticketSystem.autodeleteRequiresClosedTicket && !ticket.get("opendiscord:closed").value
const enabled = (disableOnClaim || disableWhenNotClosed || !ticket.get("opendiscord:autodelete-enabled").value) ? false : ticket.option.get("opendiscord:autodelete-enable-leave") const enabled = (disableOnClaim || disableWhenNotClosed || !ticket.get("opendiscord:autodelete-enabled").value) ? false : ticket.option.get("opendiscord:autodelete-enable-leave")
if (enabled){ if (enabled){
+5 -5
View File
@@ -14,8 +14,8 @@ export async function loadAllSlashCommands(){
if (!generalConfig.data.slashCommands) return if (!generalConfig.data.slashCommands) return
const allowedCommands: string[] = [] const allowedCommands: string[] = []
for (const key in generalConfig.data.system.permissions){ for (const key in generalConfig.data.permissions){
if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key) if (generalConfig.data.permissions[key] != "none") allowedCommands.push(key)
} }
//HELP //HELP
@@ -87,7 +87,7 @@ export async function loadAllSlashCommands(){
})) }))
//DELETE //DELETE
if (allowedCommands.includes("delete") && generalConfig.data.system.enableDeleteWithoutTranscript) commands.add(new api.ODSlashCommand("opendiscord:delete",{ if (allowedCommands.includes("delete") && generalConfig.data.ticketSystem.enableDeleteWithoutTranscript) commands.add(new api.ODSlashCommand("opendiscord:delete",{
type:act.ChatInput, type:act.ChatInput,
name:"delete", name:"delete",
description:lang.getTranslation("commands.delete"), description:lang.getTranslation("commands.delete"),
@@ -654,8 +654,8 @@ export async function loadAllTextCommands(){
}) })
const allowedCommands: string[] = [] const allowedCommands: string[] = []
for (const key in generalConfig.data.system.permissions){ for (const key in generalConfig.data.permissions){
if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key) if (generalConfig.data.permissions[key] != "none") allowedCommands.push(key)
} }
//HELP //HELP

Some files were not shown because too many files have changed in this diff Show More