diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 59c6ac0..c7cc36e 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1,7 +1,7 @@
# Contributing Guidelines
-[](https://discord.com/invite/26vT9wt3n3) [](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.1.3) [](https://github.com/sponsors/DJj123dj)
+[](https://discord.com/invite/26vT9wt3n3) [](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.2.0) [](https://github.com/sponsors/DJj123dj)
These are the Contributing Guidelines of Open Ticket!
Here you can find everything you need to know about contributing to Open Ticket.
diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index 3f704b6..a381a61 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -19,18 +19,15 @@ This list will be updated on every release.
| Version | Supported | Notes |
|------------|-----------|---------------------------------------------------------------|
-| 4.2.0 | ๐ฆ | In Development |
-| 4.1.x | ๐ฆ | In Development |
-| 4.1.3 | โ
| |
-| 4.1.2 | โ
| |
-| 4.1.1 | โ
| Supported Until April 2026 (LTS) |
+| 4.2.x | ๐ฆ | In Development |
+| 4.2.1 | ๐ฆ | In Development |
+| 4.2.0 | โ
| |
+| 4.1.3 | โ
| (LTS) Long-Term-Support, Until September 2026 |
+| 4.1.2 | ๐ง | |
+| 4.1.1 | ๐ง | |
| 4.1.0 | ๐ง | |
-| 4.0.7 | ๐ง | |
-| 4.0.6 | ๐ง | |
-| 4.0.5 | ๐ง | Deprecated |
-| 4.0.4 | ๐ง | Deprecated |
-| < 4.0.4 | ๐ง | Deprecated, Transcripts v2.0, Documentation Only |
-| < 4.0.0 | โ | |
+| 4.0.7 | ๐ง | Deprecated |
+| < 4.0.7 | โ | |
### ๐ท๏ธ Reporting Vulnerabilities
You can report vulnerabilities, errors & bugs using one of the following methods:
diff --git a/.gitignore b/.gitignore
index 243efae..193d71e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,7 +17,11 @@ otdebug.txt
*/*/*/.DS_Store
**/.DS_Store
-.docs/*
-!.docs/createDocs.js
-!.docs/mergeTranslations.js
-!.docs/typedoc-config.json
\ No newline at end of file
+.backup/*
+.tools/*
+!.tools/createDocs.js
+!.tools/mergeTranslations.js
+!.tools/typedoc-config.json
+!.tools/pterodactyl-eggs/
+!.tools/docker-compose.yml
+!.tools/dockerfile
\ No newline at end of file
diff --git a/.docs/createDocs.js b/.tools/createDocs.js
similarity index 100%
rename from .docs/createDocs.js
rename to .tools/createDocs.js
diff --git a/docker-compose.yml b/.tools/docker-compose.yml
similarity index 100%
rename from docker-compose.yml
rename to .tools/docker-compose.yml
diff --git a/dockerfile b/.tools/dockerfile
similarity index 83%
rename from dockerfile
rename to .tools/dockerfile
index 4a0acad..514203f 100644
--- a/dockerfile
+++ b/.tools/dockerfile
@@ -1,6 +1,6 @@
# Docker File for Open Ticket v4
-# Use the official Node.js 20 image from Docker Hub
-FROM node:20-alpine
+# Use the official Node.js 22 image from Docker Hub
+FROM node:22-alpine
# Set pterodactyl working directory inside the container
WORKDIR /home/container
diff --git a/.docs/mergeTranslations.js b/.tools/mergeTranslations.js
similarity index 100%
rename from .docs/mergeTranslations.js
rename to .tools/mergeTranslations.js
diff --git a/.eggs/README.md b/.tools/pterodactyl-eggs/README.md
similarity index 91%
rename from .eggs/README.md
rename to .tools/pterodactyl-eggs/README.md
index 4585e89..c22f4a4 100644
--- a/.eggs/README.md
+++ b/.tools/pterodactyl-eggs/README.md
@@ -2,7 +2,7 @@
[](https://discord.com/invite/26vT9wt3n3)
-[](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.1.3)
+[](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.2.0)
[](https://github.com/sponsors/DJj123dj)
[](.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)
- 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)
- This egg will always use Open Ticket `v4.1.3`. Open Ticket updates will not have an effect on this egg.
diff --git a/.eggs/openticket-egg-dev.json b/.tools/pterodactyl-eggs/openticket-egg-dev.json
similarity index 100%
rename from .eggs/openticket-egg-dev.json
rename to .tools/pterodactyl-eggs/openticket-egg-dev.json
diff --git a/.eggs/openticket-egg-main.json b/.tools/pterodactyl-eggs/openticket-egg-main.json
similarity index 100%
rename from .eggs/openticket-egg-main.json
rename to .tools/pterodactyl-eggs/openticket-egg-main.json
diff --git a/.eggs/openticket-egg-v3.5.9.json b/.tools/pterodactyl-eggs/openticket-egg-v3.5.9.json
similarity index 100%
rename from .eggs/openticket-egg-v3.5.9.json
rename to .tools/pterodactyl-eggs/openticket-egg-v3.5.9.json
diff --git a/.eggs/openticket-egg-v4.0.7.json b/.tools/pterodactyl-eggs/openticket-egg-v4.0.7.json
similarity index 100%
rename from .eggs/openticket-egg-v4.0.7.json
rename to .tools/pterodactyl-eggs/openticket-egg-v4.0.7.json
diff --git a/.eggs/openticket-egg-v4.1.0.json b/.tools/pterodactyl-eggs/openticket-egg-v4.1.0.json
similarity index 100%
rename from .eggs/openticket-egg-v4.1.0.json
rename to .tools/pterodactyl-eggs/openticket-egg-v4.1.0.json
diff --git a/.eggs/openticket-egg-v4.1.1.json b/.tools/pterodactyl-eggs/openticket-egg-v4.1.1.json
similarity index 100%
rename from .eggs/openticket-egg-v4.1.1.json
rename to .tools/pterodactyl-eggs/openticket-egg-v4.1.1.json
diff --git a/.eggs/openticket-egg-v4.1.2.json b/.tools/pterodactyl-eggs/openticket-egg-v4.1.2.json
similarity index 100%
rename from .eggs/openticket-egg-v4.1.2.json
rename to .tools/pterodactyl-eggs/openticket-egg-v4.1.2.json
diff --git a/.eggs/openticket-egg-v4.1.3.json b/.tools/pterodactyl-eggs/openticket-egg-v4.1.3.json
similarity index 100%
rename from .eggs/openticket-egg-v4.1.3.json
rename to .tools/pterodactyl-eggs/openticket-egg-v4.1.3.json
diff --git a/.tools/pterodactyl-eggs/openticket-egg-v4.2.0.json b/.tools/pterodactyl-eggs/openticket-egg-v4.2.0.json
new file mode 100644
index 0000000..88530ca
--- /dev/null
+++ b/.tools/pterodactyl-eggs/openticket-egg-v4.2.0.json
@@ -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"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.docs/typedoc-config.json b/.tools/typedoc-config.json
similarity index 100%
rename from .docs/typedoc-config.json
rename to .tools/typedoc-config.json
diff --git a/README.md b/README.md
index 48f8a8f..16c90c3 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
Related Projects:
-
+
@@ -17,7 +17,7 @@
Open Ticket is the most advanced and customizable Discord ticket bot available. With 350+ configurable settings , you have full control over every aspect of your ticket system!
From HTML transcripts and Advanced Plugins to Claiming & Pinning, Questions & Modals, Detailed Statistics, and much more.
-The bot is fully translated into 36+ languages and has been battle-tested in large Discord servers.
+The bot is fully translated into 37+ languages and has been battle-tested in large Discord servers.
Need help or want to get involved? Feel free to join our Discord server .
@@ -25,7 +25,7 @@ Need help or want to get involved? Feel free to join our โค๏ธ Love Open Ticket? Sponsorships help fuel our HTML transcript servers and future features! โค๏ธ
---
-> **[-> Navigate to (โฑ๏ธ Quick Setup)](#๏ธ-quick-start-using-cli)**
+> **[-> Navigate to (โฑ๏ธ Quick Setup)](#๏ธ-quick-start-using-interactive-cli-tool)**
> **[-> Navigate to (๐ Documentation)](https://otdocs.dj-dj.be)**
> **[-> Navigate to (๐ Support Server)](https://discord.dj-dj.be)**
@@ -37,7 +37,7 @@ Need help or want to get involved? Feel free to join our > "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"
+ }
+}
\ No newline at end of file
diff --git a/config/options.json b/config/options.json
deleted file mode 100644
index 981a1bc..0000000
--- a/config/options.json
+++ /dev/null
@@ -1,126 +0,0 @@
-[
- {
- "id":"example-ticket",
- "name":"Question",
- "description":"Create this ticket if you have a question! (or leave empty)",
- "type":"ticket",
-
- "button":{
- "emoji":"๐ซ (or leave empty)",
- "label":"question (or leave empty)",
- "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 (or leave empty)",
- "closedCategory":"category id (or leave empty)",
- "backupCategory":"category id (or leave empty)",
- "claimedCategory":[
- {"user":"user id","category":"category id"}
- ],
- "topic":"This is the topic of this ticket channel and is visible to everyone! (or leave empty)"
- },
-
- "dmMessage":{
- "enabled":false,
- "text":"Thank you for creating a ticket in our server! (or leave empty)",
- "embed":{
- "enabled":false,
- "title":"Embed Title! (or leave empty)",
- "description":"Description (or leave empty)",
- "customColor":"#f8ab00 (or leave empty)",
-
- "image":"https://www.example.com/image.png (or leave empty)",
- "thumbnail":"https://www.example.com/image.png (or leave empty)",
- "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 'Question' ticket in our server!\nOur support team will help you as soon as possible!",
- "customColor":"#f8ab00 (or leave empty)",
-
- "image":"https://www.example.com/image.png (or leave empty)",
- "thumbnail":"https://www.example.com/image.png (or leave empty)",
- "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":"Go to our website.",
- "type":"website",
-
- "button":{
- "emoji":"๐",
- "label":"Visit our website"
- },
-
- "url":"https://www.dj-dj.be"
- },
- {
- "id":"example-role",
- "name":"Update Ping",
- "description":"Click here to get notified on 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
- }
-]
\ No newline at end of file
diff --git a/config/options.jsonc b/config/options.jsonc
new file mode 100644
index 0000000..1948f6e
--- /dev/null
+++ b/config/options.jsonc
@@ -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)
+ }
+]
\ No newline at end of file
diff --git a/config/panels.json b/config/panels.json
deleted file mode 100644
index acc1093..0000000
--- a/config/panels.json
+++ /dev/null
@@ -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 clicking one of the buttons below!",
-
- "customColor":"#f8ab00 (or leave empty)",
- "url":"https://openticket.dj-dj.be (or leave empty)",
-
- "image":"https://www.example.com/image.png (or leave empty)",
- "thumbnail":"https://www.example.com/image.png (or leave empty)",
-
- "footer":"Open Ticket v4.1.3 (or leave empty)",
- "fields":[
- {"name":"field name","value":"field value","inline":false}
- ],
- "timestamp":false
- },
- "settings":{
- "dropdownPlaceholder":"Create a ticket!",
-
- "enableMaxTicketsWarningInText":false,
- "enableMaxTicketsWarningInEmbed":true,
-
- "describeOptionsLayout":"simple OR normal OR detailed",
- "describeOptionsCustomTitle":"",
- "describeOptionsInText":false,
- "describeOptionsInEmbedFields":true,
- "describeOptionsInEmbedDescription":false
- }
- }
-]
\ No newline at end of file
diff --git a/config/panels.jsonc b/config/panels.jsonc
new file mode 100644
index 0000000..cf5bca8
--- /dev/null
+++ b/config/panels.jsonc
@@ -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
+ *
+ * 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
+ }
+ }
+]
\ No newline at end of file
diff --git a/config/questions.json b/config/questions.json
deleted file mode 100644
index 0d2556e..0000000
--- a/config/questions.json
+++ /dev/null
@@ -1,28 +0,0 @@
-[
- {
- "id":"example-question-1",
- "name":"Example Question 1",
- "type":"short",
-
- "required":true,
- "placeholder":"Insert your short answer here!",
- "length":{
- "enabled":false,
- "min":0,
- "max":1000
- }
- },
- {
- "id":"example-question-2",
- "name":"Example Question 2",
- "type":"paragraph",
-
- "required":false,
- "placeholder":"Insert your long answer here!",
- "length":{
- "enabled":false,
- "min":0,
- "max":1000
- }
- }
-]
\ No newline at end of file
diff --git a/config/questions.jsonc b/config/questions.jsonc
new file mode 100644
index 0000000..8f9062e
--- /dev/null
+++ b/config/questions.jsonc
@@ -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."
+ }
+]
\ No newline at end of file
diff --git a/config/transcripts.json b/config/transcripts.json
deleted file mode 100644
index 37651ae..0000000
--- a/config/transcripts.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "general":{
- "enabled":false,
-
- "enableChannel":false,
- "enableCreatorDM":false,
- "enableParticipantDM":false,
- "enableActiveAdminDM":false,
- "enableEveryAdminDM":false,
-
- "channel":"transcript channel id (or leave empty)",
- "mode":"html OR text"
- },
- "embedSettings":{
- "customColor":"#f8ab00 (or leave empty)",
- "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":"this-is-a-transcript (or leave empty)"
- },
- "htmlTranscriptStyle":{
- "background":{
- "enableCustomBackground":false,
- "backgroundColor":"#f8ba00 (or leave empty)",
- "backgroundImage":"https://www.example.com/image.png (or leave empty)"
- },
- "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"
- }
- }
-}
\ No newline at end of file
diff --git a/config/transcripts.jsonc b/config/transcripts.jsonc
new file mode 100644
index 0000000..2a441c5
--- /dev/null
+++ b/config/transcripts.jsonc
@@ -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"
+ }
+ }
+}
\ No newline at end of file
diff --git a/database/states.json b/database/states.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/database/states.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/index.js b/index.js
index 6cead33..2935154 100644
--- a/index.js
+++ b/index.js
@@ -4,7 +4,6 @@ const flags = [
//PTERODACTYL PANEL
//add startup flags here (e.g. "--no-compile") when running via the panel
]
-process.argv.push(...flags)
/////////////// STARTUP FLAGS ///////////////
/*
@@ -14,170 +13,19 @@ process.argv.push(...flags)
โโโ โโโโโโโโโโ โโโโโโ โโโโโโโโโโ โโโ โโโโโโ โโโโโโโ โโโโโโ โโโ
โโโโโโโโโโโโ โโโโโโโโโโโ โโโโโโ โโโ โโโโโโโโโโโโโโ โโโโโโโโโโโ โโโ
โโโโโโโ โโโ โโโโโโโโโโโ โโโโโ โโโ โโโ โโโโโโโโโโ โโโโโโโโโโโ โโโ
- v4.1.3 - Made by DJj123dj & Contributors
+ v4.2.0 - Made by DJj123dj & Contributors
Discord: https://discord.dj-dj.be
Docs: https://otdocs.dj-dj.be
Support Us: https://github.com/sponsors/DJj123dj/
*/
+
///////////////////////////////////////////
////////// COMPILATION + STARTUP //////////
///////////////////////////////////////////
-const fs = require("fs")
-const ts = require("typescript")
-const {createHash,Hash} = require("crypto")
-const nodepath = require('path')
-const ansis = require("ansis")
-/** ## What is this?
- * This is a function which compares `./src/` with a hash stored in `./dist/hash.txt`.
- * The hash is based on the modified date & file metadata of all files in `./src/`.
- *
- * If the hash is different, the bot will automatically re-compile.
- * This will help you save CPU resources because the bot shouldn't re-compile when nothing has been changed :)
- *
- * @param {string} dir
- * @param {Hash|null} upperHash
- */
-function computeSourceHash(dir,upperHash){
- const hash = upperHash ? upperHash : createHash("sha256")
- const info = fs.readdirSync(dir,{withFileTypes:true})
-
- for (const file of info) {
- const fullPath = nodepath.join(dir,file.name)
- if (file.isFile() && [".js",".ts",".jsx",".tsx"].some((ext) => file.name.endsWith(ext))){
- const statInfo = fs.statSync(fullPath)
- //compute hash using file metadata
- const fileInfo = `${fullPath}:${statInfo.size}:${statInfo.mtimeMs}`
- hash.update(fileInfo)
-
- }else if (file.isDirectory()){
- //recursively compute all folders
- computeSourceHash(fullPath,hash)
- }
- }
- //return when not being called recursively
- if (!upperHash) {
- return hash.digest("hex")
- }
-}
-function requiresCompilation(){
- //check hashes when not using "--compile-only" flag
- if (process.argv.includes("--compile-only")) return true
-
- console.log("OT: Comparing prebuilds with source...")
- const sourceHash = computeSourceHash("./src/")
- const pluginHash = computeSourceHash("./plugins/")
- const hash = sourceHash+":"+pluginHash
-
- if (fs.existsSync("./dist/hash.txt")){
- const distHash = fs.readFileSync("./dist/hash.txt").toString()
- if (distHash === hash) return false
- else return true
- }else return true
-}
-function saveNewCompilationHash(){
- const sourceHash = computeSourceHash("./src/")
- const pluginHash = computeSourceHash("./plugins/")
- const hash = sourceHash+":"+pluginHash
- fs.writeFileSync("./dist/hash.txt",hash)
-}
-
-if (!process.argv.includes("--no-compile")){
- const requiredDependencies = new Set()
- if (fs.existsSync("./plugins")){
- console.log("OT: Reading plugin.json files...")
- for (const pluginDir of fs.readdirSync("./plugins")){
- if (pluginDir === ".DS_Store") continue
- const pluginPath = nodepath.join("./plugins", pluginDir)
- if (!fs.statSync(pluginPath).isDirectory()) continue
-
- const pluginJsonPath = nodepath.join(pluginPath, "plugin.json")
- if (fs.existsSync(pluginJsonPath)){
- try{
- const pluginData = JSON.parse(fs.readFileSync(pluginJsonPath).toString())
- if (pluginData.npmDependencies && Array.isArray(pluginData.npmDependencies)){
- pluginData.npmDependencies.forEach((dep) => {
- if (typeof dep === "string" && dep.trim()){
- requiredDependencies.add(dep.trim())
- }
- })
- }
- }catch(err){
- // skip invalid plugin.json files, will be caught later
- }
- }
- }
-
- if (requiredDependencies.size > 0){
- console.log("OT: Checking plugin npm dependencies...")
- /**@type {string[]} */
- const missingDeps = []
- for (const dep of requiredDependencies){
- try{
- require.resolve(dep)
- }catch(err){
- missingDeps.push(dep)
- }
- }
-
- if (missingDeps.length > 0){
- console.log(ansis.red("OT: โ Fatal Error --> Missing npm dependencies required by plugins:\n\n")+ansis.cyan(missingDeps.map((dep) => " - "+dep).join("\n")+"\n"))
- console.log("OT: Please install missing dependencies using the following command:\n> "+ansis.bold.green("npm install " + missingDeps.join(" "))+"\n")
- process.exit(1)
- }
- }
- }
-
- if (requiresCompilation()){
- console.log("OT: Compilation Required...")
-
- //REMOVE EXISTING BUILDS
- console.log("OT: Removing Prebuilds...")
- fs.rmSync("./dist",{recursive:true,force:true})
-
- //COMPILE TYPESCRIPT
- console.log("OT: Compiling Typescript...")
- const configPath = nodepath.resolve('./tsconfig.json')
- const configFile = ts.readConfigFile(configPath,ts.sys.readFile)
-
- //check for tsconfig errors
- if (configFile.error){
- const message = ts.formatDiagnosticsWithColorAndContext([configFile.error],ts.createCompilerHost({}))
- console.error(message)
- process.exit(1)
- }
-
- //parse tsconfig file
- const parsedConfig = ts.parseJsonConfigFileContent(configFile.config,ts.sys,nodepath.dirname(configPath))
-
- //create program/compiler
- const program = ts.createProgram({
- rootNames:parsedConfig.fileNames,
- options:parsedConfig.options
- })
-
- //emit all compiled files
- const emitResult = program.emit()
-
- //print emit errors/warnings (type errors)
- const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics)
- const formattedDiagnostics = ts.formatDiagnosticsWithColorAndContext(allDiagnostics, ts.createCompilerHost(parsedConfig.options))
- console.log(formattedDiagnostics)
-
- if (emitResult.emitSkipped || allDiagnostics.find((d) => d.category == ts.DiagnosticCategory.Error || d.category == ts.DiagnosticCategory.Warning)){
- console.log("OT: Compilation Failed!")
- process.exit(1)
- }
- }else console.log("OT: No Compilation Required...")
-
- //save new compilation hash
- saveNewCompilationHash()
-}
-
-//START BOT
-console.log("OT: Compilation Succeeded!")
-if (process.argv.includes("--compile-only")) process.exit(0) //exit when only compile is required!
-console.log("OT: Starting Bot!")
-require("./dist/src/index.js")
\ No newline at end of file
+import { frameworkStartup } from "@open-discord-bots/framework"
+frameworkStartup(flags,"openticket",async () => {
+ await import("./dist/src/index.js")
+})
\ No newline at end of file
diff --git a/languages/arabic.json b/languages/arabic.json
index 694bf33..40c7cff 100644
--- a/languages/arabic.json
+++ b/languages/arabic.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["palestinian"],
"lastedited":"16/02/2026",
"language":"Arabic",
diff --git a/languages/bengali.json b/languages/bengali.json
index fe5894f..317f3d5 100644
--- a/languages/bengali.json
+++ b/languages/bengali.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["HanumeshGupta"],
"lastedited":"16/02/2026",
"language":"Bengali",
diff --git a/languages/catalan.json b/languages/catalan.json
index 1336d34..fed41c0 100644
--- a/languages/catalan.json
+++ b/languages/catalan.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["guillee3"],
"lastedited":"16/02/2026",
"language":"Catalan",
diff --git a/languages/custom.json b/languages/custom.json
index 7b9888d..f22936f 100644
--- a/languages/custom.json
+++ b/languages/custom.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["DJj123dj"],
"lastedited":"16/02/2026",
"language":"Custom",
@@ -13,94 +13,94 @@
"typeWarning":"[WARNING]",
"typeInfo":"[INFO]",
"headerConfigChecker":"CONFIG CHECKER",
- "headerDescription":"check for errors in your config files!",
- "footerError":"the bot won't start until all {0}'s are fixed!",
- "footerWarning":"it's recommended to fix all {0}'s before starting!",
+ "headerDescription":"Validating config files...",
+ "footerError":"The bot will not start until all {0}'s are resolved.",
+ "footerWarning":"The bot may behave unexpectedly until all {0}'s are resolved.",
"footerSupport":"SUPPORT: {0} - DOCS: {1}",
- "compactInformation":"use {0} for more information!",
+ "compactInformation":"Use {0} for a detailed config report.",
"dataPath":"path",
"dataDocs":"docs",
"dataMessages":"message"
},
"messages":{
- "stringTooShort":"This string can't be shorter than {0} characters!",
- "stringTooLong":"This string can't be longer than {0} characters!",
- "stringLengthInvalid":"This string needs to be {0} characters long!",
- "stringStartsWith":"This string needs to start with {0}!",
- "stringEndsWith":"This string needs to end with {0}!",
- "stringContains":"This string needs to contain {0}!",
- "stringChoices":"This string can only be one of the following values: {0}!",
- "stringRegex":"This string is invalid!",
- "stringInvertedContains":"This string is not allowed to contain {0}!",
- "stringLowercase":"This string must be written in lowercase only!",
- "stringUppercase":"This string must be written in uppercase only!",
- "stringSpecialCharacters":"This string is not allowed to contain any special characters! (a-z, 0-9 & space only)",
- "stringNoSpaces":"This string is not allowed to contain spaces!",
- "stringCapitalWord":"It's recommended that each word in this string starts with a capital letter!",
- "stringCapitalSentence":"It looks like some sentences in this string don't start with a capital letter!",
- "stringPunctuation":"It looks like the sentence in this string doesn't end with a punctuation mark!",
+ "stringTooShort":"Text must be at least {0} characters long",
+ "stringTooLong":"Text must be no longer than {0} characters",
+ "stringLengthInvalid":"Text must be exactly {0} characters long",
+ "stringStartsWith":"Text must start with {0}",
+ "stringEndsWith":"Text must end with {0}",
+ "stringContains":"Text must contain {0}",
+ "stringChoices":"Text must be one of the following: {0}",
+ "stringRegex":"Text does not match the required format",
+ "stringInvertedContains":"Text must not contain {0}",
+ "stringLowercase":"Text must be entirely lowercase",
+ "stringUppercase":"Text must be entirely uppercase",
+ "stringSpecialCharacters":"Text must only contain letters (aโz), numbers (0โ9), and spaces",
+ "stringNoSpaces":"Text must not contain spaces",
+ "stringCapitalWord":"Each word in this value should start with a capital letter",
+ "stringCapitalSentence":"One or more sentences in this value do not start with a capital letter",
+ "stringPunctuation":"The sentence in this value does not end with a punctuation mark",
- "numberTooShort":"This number can't be shorter than {0} characters!",
- "numberTooLong":"This number can't be longer than {0} characters!",
- "numberLengthInvalid":"This number needs to be {0} characters long!",
- "numberTooSmall":"This number needs to be at least {0}!",
- "numberTooLarge":"This number needs to be at most {0}!",
- "numberNotEqual":"This number needs to be {0}!",
- "numberStep":"This number needs to be a multiple of {0}!",
- "numberStepOffset":"This number needs to be a multiple of {0} starting with {1}!",
- "numberStartsWith":"This number needs to start with {0}!",
- "numberEndsWith":"This number needs to end with {0}!",
- "numberContains":"This number needs to contain {0}!",
- "numberChoices":"This number can only be one of the following values: {0}!",
- "numberFloat":"This number can't be a decimal!",
- "numberNegative":"This number can't be negative!",
- "numberPositive":"This number can't be positive!",
- "numberZero":"This number can't be zero!",
- "numberNan":"This number can't be NaN (Not A Number)!",
- "numberInvertedContains":"This number is not allowed to contain {0}!",
+ "numberTooShort":"Number must be at least {0} digits long",
+ "numberTooLong":"Number must be no longer than {0} digits",
+ "numberLengthInvalid":"Number must be exactly {0} digits long",
+ "numberTooSmall":"Number must be at least {0}",
+ "numberTooLarge":"Number must be at most {0}",
+ "numberNotEqual":"Number must be exactly {0}",
+ "numberStep":"Number must be a multiple of {0}",
+ "numberStepOffset":"Number must be a multiple of {0}, starting from {1}",
+ "numberStartsWith":"Number must start with {0}",
+ "numberEndsWith":"Number must end with {0}",
+ "numberContains":"Number must contain {0}",
+ "numberChoices":"Number must be one of the following: {0}",
+ "numberFloat":"Number must be a whole number",
+ "numberNegative":"Number must be a positive number",
+ "numberPositive":"Number must be a negative number",
+ "numberZero":"Number must not be zero",
+ "numberNan":"Number must be a valid number",
+ "numberInvertedContains":"Number must not contain {0}",
- "booleanTrue":"This boolean can't be true!",
- "booleanFalse":"This boolean can't be false!",
+ "booleanTrue":"Boolean must be false",
+ "booleanFalse":"Boolean must be true",
+
+ "arrayEmptyDisabled":"List must not be empty",
+ "arrayEmptyRequired":"List must be empty",
+ "arrayTooShort":"List must have at least {0} items",
+ "arrayTooLong":"List must have at most {0} items",
+ "arrayLengthInvalid":"List must have exactly {0} items",
+ "arrayInvalidTypes":"List may only contain the following types: {0}",
+ "arrayDouble":"List must not contain duplicate values",
+
+ "discordInvalidId":"Invalid Discord {0} ID",
+ "discordInvalidIdOptions":"Invalid Discord {0} ID. Alternatively, use one of the following: {1}",
+ "discordInvalidToken":"Invalid Discord token",
+ "colorInvalid":"Invalid hex color",
+ "emojiTooShort":"Value must contain at least {0} emoji",
+ "emojiTooLong":"Value must contain at most {0} emoji",
+ "emojiCustom":"Custom Discord emojis are not allowed here",
+ "emojiInvalid":"Invalid emoji",
+ "urlInvalid":"Invalid URL",
+ "urlInvalidHttp":"URL must use the https:// protocol",
+ "urlInvalidProtocol":"URL must use the http:// or https:// protocol",
+ "urlInvalidHostname":"URL hostname is not allowed",
+ "urlInvalidExtension":"Invalid URL extension. Allowed extensions: {0}",
+ "urlInvalidPath":"Invalid URL path",
+ "idNotUnique":"This ID is already in use. Please choose a unique ID",
+ "idNonExistent":"ID {0} does not exist",
+
+ "invalidType":"Property must be of type: {0}",
+ "propertyMissing":"Required property {0} is missing from the object",
+ "propertyOptional":"Property {0} is optional in the object",
+ "objectDisabled":"This object is disabled. Enable it using {0}",
+ "nullInvalid":"Property must not be null",
+ "switchInvalidType":"Value must be one of the following types: {0}",
+ "objectSwitchInvalid":"Object must be one of the following types: {0}",
- "arrayEmptyDisabled":"This array isn't allowed to be empty!",
- "arrayEmptyRequired":"This array is required to be empty!",
- "arrayTooShort":"This array needs to have a length of at least {0}!",
- "arrayTooLong":"This array needs to have a length of at most {0}!",
- "arrayLengthInvalid":"This array needs to have a length of {0}!",
- "arrayInvalidTypes":"This array can only contain the following types: {0}!",
- "arrayDouble":"This array doesn't allow the same value twice!",
-
- "discordInvalidId":"This is an invalid discord {0} id!",
- "discordInvalidIdOptions":"This is an invalid discord {0} id! You can also use one of these: {1}!",
- "discordInvalidToken":"This is an invalid discord token (syntactically)!",
- "colorInvalid":"This is an invalid hex color!",
- "emojiTooShort":"This string needs to have at least {0} emoji's!",
- "emojiTooLong":"This string needs to have at most {0} emoji's!",
- "emojiCustom":"This emoji can't be a custom discord emoji!",
- "emojiInvalid":"This is an invalid emoji!",
- "urlInvalid":"This url is invalid!",
- "urlInvalidHttp":"This url can only use the https:// protocol!",
- "urlInvalidProtocol":"This url can only use the http:// & https:// protocols!",
- "urlInvalidHostname":"This url has a disallowed hostname!",
- "urlInvalidExtension":"This url has an invalid extension! Choose between: {0}!",
- "urlInvalidPath":"This url has an invalid path!",
- "idNotUnique":"This id isn't unique, use another id instead!",
- "idNonExistent":"The id {0} doesn't exist!",
-
- "invalidType":"This property needs to be the type: {0}!",
- "propertyMissing":"The property {0} is missing from this object!",
- "propertyOptional":"The property {0} is optional in this object!",
- "objectDisabled":"This object is disabled, enable it using {0}!",
- "nullInvalid":"This property can't be null!",
- "switchInvalidType":"This needs to be one of the following types: {0}!",
- "objectSwitchInvalid":"This object needs to be one of the following types: {0}!",
-
- "invalidLanguage":"This is an invalid language!",
- "invalidButton":"This button needs to have at least an {0} or {1}!",
- "unusedOption":"The option {0} isn't used anywhere!",
- "unusedQuestion":"The question {0} isn't used anywhere!",
- "dropdownOption":"A panel with dropdown enabled can only contain options of the 'ticket' type!",
- "customInvalidVersion":"The version specified in your config does not match! Make sure you have updated the config to the latest version!"
+ "invalidLanguage":"Invalid language",
+ "invalidButton":"Button must have at least an {0} or {1}",
+ "unusedOption":"Option {0} is not used anywhere",
+ "unusedQuestion":"Question {0} is not used anywhere",
+ "dropdownOption":"Panels with dropdown enabled may only contain options of the 'ticket' type",
+ "customInvalidVersion":"Config version mismatch. Make sure to update your config to the latest version"
}
},
"actions":{
@@ -159,118 +159,118 @@
"transfer":"Ticket Transferred"
},
"descriptions":{
- "create":"Your ticket has been created. Click the button below to access it!",
- "close":"The ticket has been closed successfully!",
- "delete":"The ticket has been deleted successfully!",
- "reopen":"The ticket has been reopened successfully!",
- "claim":"The ticket has been claimed successfully!",
- "unclaim":"The ticket has been unclaimed successfully!",
- "pin":"The ticket has been pinned successfully!",
- "unpin":"The ticket has been unpinned successfully!",
- "rename":"The ticket has been renamed to {0} successfully!",
- "move":"The ticket has been moved to {0} successfully!",
- "add":"{0} has been added to the ticket successfully!",
- "remove":"{0} has been removed from the ticket successfully!",
+ "create":"Your ticket is ready. Click the button below to view and continue.",
+ "close":"The ticket has been closed.",
+ "delete":"The ticket has been deleted.",
+ "reopen":"The ticket has been reopened.",
+ "claim":"The ticket has been claimed.",
+ "unclaim":"The ticket has been unclaimed.",
+ "pin":"The ticket has been pinned.",
+ "unpin":"The ticket has been unpinned.",
+ "rename":"The ticket has been renamed to {0}.",
+ "move":"The ticket has been moved to {0}.",
+ "add":"{0} has been added to the ticket.",
+ "remove":"{0} has been removed from the ticket.",
"helpExplanation":"`` => required parameter\n`[name]` => optional parameter",
- "statsReset":"The bot stats have been reset successfully!",
- "statsError":"Unable to view ticket stats!\n{0} is not a ticket!",
- "blacklistAdd":"{0} has been blacklisted successfully!",
- "blacklistRemove":"{0} has been released successfully!",
- "blacklistGetSuccess":"{0} is currently blacklisted!",
- "blacklistGetEmpty":"{0} is currently not blacklisted!",
- "blacklistViewEmpty":"No-one has been blacklisted yet!",
- "blacklistViewTip":"Use \"/blacklist add\" to blacklist a user!",
- "clearVerify":"Are you sure you want to delete multiple tickets?\nThis action can't be undone!",
- "clearReady":"{0} tickets have been deleted successfully!",
- "rolesEmpty":"No roles have been updated!",
+ "statsReset":"The bot statistics have been reset.",
+ "statsError":"Unable to retrieve ticket statistics.\n{0} is not a valid ticket.",
+ "blacklistAdd":"{0} has been blacklisted.",
+ "blacklistRemove":"{0} has been released.",
+ "blacklistGetSuccess":"{0} is blacklisted!",
+ "blacklistGetEmpty":"{0} is not blacklisted!",
+ "blacklistViewEmpty":"No users have been blacklisted yet.",
+ "blacklistViewTip":"Use \"/blacklist add\" to add a user to the blacklist.",
+ "clearVerify":"Are you sure you want to delete multiple tickets?\nThis action cannot be undone.",
+ "clearReady":"{0} ticket(s) have been deleted.",
+ "rolesEmpty":"No roles were modified.",
- "autocloseLeave":"This ticket has been autoclosed because the creator left the server!",
- "autocloseTimeout":"This ticket has been autoclosed because it has been inactive for more than `{0}h`!",
- "autodeleteLeave":"This ticket has been autodeleted because the creator left the server!",
- "autodeleteTimeout":"This ticket has been autodeleted because it has been inactive for more than `{0} days`!",
- "autocloseEnabled":"Autoclose has been enabled in this ticket!\nIt will be closed when it is inactive for more than `{0}h`!",
- "autocloseDisabled":"Autoclose has been disabled in this ticket!\nIt won't be closed automatically anymore!",
- "autodeleteEnabled":"Autodelete has been enabled in this ticket!\nIt will be deleted when it is inactive for more than `{0} days`!",
- "autodeleteDisabled":"Autodelete has been disabled in this ticket!\nIt won't be deleted automatically anymore!",
+ "autocloseLeave":"This ticket was automatically closed because its creator left the server.",
+ "autocloseTimeout":"This ticket was automatically closed due to inactivity exceeding `{0}h`.",
+ "autodeleteLeave":"This ticket was automatically deleted because its creator left the server.",
+ "autodeleteTimeout":"This ticket was automatically deleted due to inactivity exceeding `{0} days`.",
+ "autocloseEnabled":"Autoclose has been enabled for this ticket.\nIt will close after `{0}h` of inactivity.",
+ "autocloseDisabled":"Autoclose has been disabled for this ticket.\nThis ticket will no longer close automatically.",
+ "autodeleteEnabled":"Autodelete has been enabled for this ticket.\nIt will be deleted after `{0} days` of inactivity.",
+ "autodeleteDisabled":"Autodelete has been disabled for this ticket.\nThis ticket will no longer be deleted automatically.",
- "ticketMessageLimit":"You can only create {0} ticket(s) at the same time!",
- "ticketMessageAutoclose":"This ticket will be autoclosed when inactive for {0}h!",
- "ticketMessageAutodelete":"This ticket will be autodeleted when inactive for {0} days!",
- "panelReady":"The panel is available in the followup message!\nThis message can now be deleted!",
+ "ticketMessageLimit":"You can only have {0} active ticket(s) at a time.",
+ "ticketMessageAutoclose":"This ticket will automatically close after `{0}h` of inactivity.",
+ "ticketMessageAutodelete":"This ticket will automatically be deleted after `{0} days` of inactivity.",
+ "panelReady":"The panel has been sent in the follow-up message.\nYou may now delete this message.",
- "topicSet":"The channel topic has been changed by {0} successfully!",
- "prioritySet":"The ticket priority has been changed to {0} by {1} successfully!",
- "priorityGet":"The current priority of this ticket is {0}.",
- "transfer":"The ticket ownership has been transferred from {0} to {1} by {2} successfully!"
+ "topicSet":"The channel topic has been changed by {0}.",
+ "prioritySet":"The ticket priority has been changed to {0} by {1}.",
+ "priorityGet":"The priority of this ticket is {0}.",
+ "transfer":"The ticket ownership has been transferred from {0} to {1} by {2}."
},
"modal":{
- "closePlaceholder":"Why did you close this ticket?",
- "deletePlaceholder":"Why did you delete this ticket?",
- "reopenPlaceholder":"Why did you reopen this ticket?",
- "claimPlaceholder":"Why did you claim this ticket?",
- "unclaimPlaceholder":"Why did you unclaim this ticket?",
- "pinPlaceholder":"Why did you pin this ticket?",
- "unpinPlaceholder":"Why did you unpin this ticket?"
+ "closePlaceholder":"Why would you like to close this ticket?",
+ "deletePlaceholder":"Why would you like to delete this ticket?",
+ "reopenPlaceholder":"Why would you like to reopen this ticket?",
+ "claimPlaceholder":"Why would you like to claim this ticket?",
+ "unclaimPlaceholder":"Why would you like to unclaim this ticket?",
+ "pinPlaceholder":"Why would you like to pin this ticket?",
+ "unpinPlaceholder":"Why would you like to unpin this ticket?"
},
"logs":{
- "createLog":"A new ticket got created by {0}!",
- "closeLog":"This ticket has been closed by {0}!",
- "closeDm":"Your ticket has been closed in our server!",
- "deleteLog":"This ticket has been deleted by {0}!",
- "deleteDm":"Your ticket has been deleted in our server!",
- "reopenLog":"This ticket has been reopened by {0}!",
- "reopenDm":"Your ticket has been reopened in our server!",
- "claimLog":"This ticket has been claimed by {0}!",
- "claimDm":"Your ticket has been claimed in our server!",
- "unclaimLog":"This ticket has been unclaimed by {0}!",
- "unclaimDm":"Your ticket has been unclaimed in our server!",
- "pinLog":"This ticket has been pinned by {0}!",
- "pinDm":"Your ticket has been pinned in our server!",
- "unpinLog":"This ticket has been unpinned by {0}!",
- "unpinDm":"Your ticket has been unpinned in our server!",
- "renameLog":"This ticket has been renamed to {0} by {1}!",
- "renameDm":"Your ticket has been renamed to {0} in our server!",
- "moveLog":"This ticket has been moved to {0} by {1}!",
- "moveDm":"Your ticket has been moved to {0} in our server!",
- "addLog":"{0} has been added to this ticket by {1}!",
- "addDm":"{0} has been added to your ticket in our server!",
- "removeLog":"{0} has been removed from this ticket by {1}!",
- "removeDm":"{0} has been removed from your ticket in our server!",
+ "createLog":"A new ticket got created by {0}.",
+ "closeLog":"This ticket has been closed by {0}.",
+ "closeDm":"Your ticket has been closed.",
+ "deleteLog":"This ticket has been deleted by {0}.",
+ "deleteDm":"Your ticket has been deleted.",
+ "reopenLog":"This ticket has been reopened by {0}.",
+ "reopenDm":"Your ticket has been reopened.",
+ "claimLog":"This ticket has been claimed by {0}.",
+ "claimDm":"Your ticket has been claimed.",
+ "unclaimLog":"This ticket has been unclaimed by {0}.",
+ "unclaimDm":"Your ticket has been unclaimed.",
+ "pinLog":"This ticket has been pinned by {0}.",
+ "pinDm":"Your ticket has been pinned.",
+ "unpinLog":"This ticket has been unpinned by {0}.",
+ "unpinDm":"Your ticket has been unpinned.",
+ "renameLog":"This ticket has been renamed to {0} by {1}.",
+ "renameDm":"Your ticket has been renamed to {0}.",
+ "moveLog":"This ticket has been moved to {0} by {1}.",
+ "moveDm":"Your ticket has been moved to {0}.",
+ "addLog":"{0} has been added to this ticket by {1}.",
+ "addDm":"{0} has been added to your ticket.",
+ "removeLog":"{0} has been removed from this ticket by {1}.",
+ "removeDm":"{0} has been removed from your ticket.",
- "blacklistAddLog":"{0} was blacklisted by {1}!",
- "blacklistRemoveLog":"{0} was removed from the blacklist by {1}!",
- "blacklistAddDm":"You have been blacklisted in our server!\nFrom now on, you are unable to create a ticket!",
- "blacklistRemoveDm":"You have been removed from the blacklist in our server!\nNow you can create tickets again!",
- "clearLog":"{0} tickets have been deleted by {1}!",
+ "blacklistAddLog":"{0} has been blacklisted by {1}.",
+ "blacklistRemoveLog":"{0} has been removed from the blacklist by {1}.",
+ "blacklistAddDm":"You have been blacklisted from this server.\nYou are no longer able to create tickets.",
+ "blacklistRemoveDm":"You have been removed from the blacklist.\nYou can now create tickets again.",
+ "clearLog":"{0} ticket(s) have been deleted by {1}.",
- "transferLog":"The ownership of this ticket has been transferred from {0} to {1} by {2}!",
- "transferDm":"The ownership of your ticket has been transferred from {0} to {1} in our server!",
- "prioritySetLog":"The priority of this ticket has been changed to {0} by {1}!",
- "prioritySetDm":"The priority of your ticket has been changed to {0} in our server!",
- "roleUpdateLog":"{0} has updated their roles!",
- "roleUpdateDm":"Your roles in our server have been updated!"
+ "transferLog":"Ticket ownership has been transferred from {0} to {1} by {2}.",
+ "transferDm":"Ownership of your ticket has been transferred from {0} to {1}.",
+ "prioritySetLog":"The priority of this ticket has been set to {0} by {1}.",
+ "prioritySetDm":"The priority of your ticket has been set to {0}.",
+ "roleUpdateLog":"{0} has modified their roles.",
+ "roleUpdateDm":"Your roles have been modified."
}
},
"transcripts":{
"success":{
"visit":"Visit Transcript",
"ready":"Transcript Created",
- "textFileDescription":"This is the text transcript of a deleted ticket!",
- "htmlProgress":"Please wait while this html transcript is getting processed...",
-
- "createdChannel":"A new {0} transcript has been created in the server!",
- "createdCreator":"A new {0} transcript has been created for one of your tickets!",
- "createdParticipant":"A new {0} transcript has been created in one of the tickets you participated in!",
- "createdActiveAdmin":"A new {0} transcript has been created in one of the tickets you participated as admin!",
- "createdEveryAdmin":"A new {0} transcript has been created in one of the tickets you were admin in!",
- "createdOther":"A new {0} transcript has been created!"
+ "textFileDescription":"This is a text transcript of a deleted ticket.",
+ "htmlProgress":"Please wait while the HTML transcript is being generated...",
+
+ "createdChannel":"A new {0} transcript has been created in the server.",
+ "createdCreator":"A new {0} transcript has been created for one of your tickets.",
+ "createdParticipant":"A new {0} transcript has been created for a ticket you participated in.",
+ "createdActiveAdmin":"A new {0} transcript has been created for a ticket you participated in as an admin.",
+ "createdEveryAdmin":"A new {0} transcript has been created for a ticket you managed as an admin.",
+ "createdOther":"A new {0} transcript has been created."
},
"errors":{
"retry":"Retry",
"continue":"Delete Without Transcript",
"backup":"Create Backup Transcript",
- "error":"Something went wrong while trying to create the transcript.\nWhat would you like to do?\n\nThis ticket won't be deleted until you click one of these buttons.",
+ "error":"Something went wrong while creating the transcript.\nWhat would you like to do?\n\nThis ticket will not be deleted until you select one of the options below.",
"title":"Transcript Error"
},
"text":{
@@ -279,7 +279,7 @@
"fileTitle":"FILE",
"fieldsTitle":"FIELDS",
"reactionsTitle":"REACTIONS",
- "statsTitle":"STATS",
+ "statsTitle":"STATISTICS",
"emptyContent":"",
"noTitle":"",
"noDesc":""
@@ -302,68 +302,68 @@
"permissionError":"Permission Error"
},
"descriptions":{
- "askForInfo":"Contact the owner of this bot for more info!",
- "askForInfoResolve":"Contact the bot owner of this bot if this issue doesn't resolve after a few tries.",
- "internalError":"Failed to respond to this {0} due to an internal error!",
- "optionMissing":"A required parameter is missing in this command!",
- "optionInvalid":"A parameter in this command is invalid!",
- "optionInvalidChoose":"Choose between",
- "unknownCommand":"Try visiting the help menu for more info!",
- "noPermissions":"You are not allowed to use this {0}!",
- "noPermissionsList":"Required Permissions: (one of them)",
- "noPermissionsCooldown":"You are not allowed to use this {0} because you have a cooldown!",
- "noPermissionsBlacklist":"You are not allowed to use this {0} because you have been blacklisted!",
- "noPermissionsLimitGlobal":"You are not allowed to create a ticket because the server reached the max tickets limit!",
- "noPermissionsLimitGlobalUser":"You are not allowed to create a ticket because you reached the max tickets limit!",
- "noPermissionsLimitOption":"You are not allowed to create a ticket because the server reached the max tickets limit for this option!",
- "noPermissionsLimitOptionUser":"You are not allowed to create a ticket because you reached the max tickets limit for this option!",
- "unknownTicket":"Try this command again in a valid ticket!",
- "deprecatedTicket":"The current channel is not a valid ticket! It might have been a ticket from an old Open Ticket version!",
- "notInGuild":"This {0} doesn't work in DM! Please try it again in a server!",
- "channelRename":"Due to discord ratelimits, it's currently impossible for the bot to rename the channel. The channel will automatically be renamed over 10 minutes if the bot isn't rebooted.",
- "channelRenameSource":"The source of this error is: {0}",
- "busy":"Unable to use this {0}!\nThe ticket is currently being processed by the bot.\n\nPlease try again in a few seconds!",
- "closeBeforeMessage":"This ticket cannot be closed/deleted before a message has been sent by a user.",
- "closeBeforeAdminMessage":"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",
- "unableToCreateTicket":"You are unable to create a ticket."
+ "askForInfo":"Please contact the bot owner for more information.",
+ "askForInfoResolve":"If the issue persists after a few attempts, please contact the bot owner.",
+ "internalError":"An internal error occurred while processing this {0}.",
+ "optionMissing":"A required parameter is missing for this command.",
+ "optionInvalid":"One or more parameters provided for this command are invalid.",
+ "optionInvalidChoose":"Please choose between",
+ "unknownCommand":"Please use the help menu for more information.",
+ "noPermissions":"You are not permitted to use this {0}.",
+ "noPermissionsList":"Required permissions (one of the following):",
+ "noPermissionsCooldown":"You cannot use this {0} while on cooldown.",
+ "noPermissionsBlacklist":"You cannot use this {0} because you are blacklisted.",
+ "noPermissionsLimitGlobal":"You cannot create a ticket because the server has reached its maximum ticket limit.",
+ "noPermissionsLimitGlobalUser":"You cannot create a ticket because you have reached your maximum ticket limit.",
+ "noPermissionsLimitOption":"You cannot create a ticket because the server has reached the maximum ticket limit for this option.",
+ "noPermissionsLimitOptionUser":"You cannot create a ticket because you have reached the maximum ticket limit for this option.",
+ "unknownTicket":"Please run this command inside a valid ticket channel.",
+ "deprecatedTicket":"This channel is not recognized as a valid ticket. It may have been created with an older version of the bot.",
+ "notInGuild":"This {0} cannot be used in direct messages. Please use it in a server.",
+ "channelRename":"Due to Discord rate limits, the channel could not be renamed immediately. It will be renamed automatically within 10 minutes if the bot remains online.",
+ "channelRenameSource":"Error source: {0}",
+ "busy":"This {0} is currently unavailable.\nThe ticket is being processed by the bot.\n\nPlease try again in a few seconds.",
+ "closeBeforeMessage":"This ticket cannot be closed or deleted before a user has sent a message.",
+ "closeBeforeAdminMessage":"This ticket cannot be closed or deleted before a support member or admin has sent a message.",
+ "unableToCreateTicket":"You are currently unable to create a ticket."
},
"optionInvalidReasons":{
- "stringRegex":"Value doesn't match pattern!",
- "stringMinLength":"Value needs to be at least {0} characters!",
- "stringMaxLength":"Value needs to be at most {0} characters!",
- "numberInvalid":"Invalid number!",
- "numberMin":"Number needs to be at least {0}!",
- "numberMax":"Number needs to be at most {0}!",
- "numberDecimal":"Number is not allowed to be a decimal!",
- "numberNegative":"Number is not allowed to be negative!",
- "numberPositive":"Number is not allowed to be positive!",
- "numberZero":"Number is not allowed to be zero!",
- "channelNotFound":"Unable to find channel!",
- "userNotFound":"Unable to find user!",
- "roleNotFound":"Unable to find role!",
- "memberNotFound":"Unable to find user!",
- "mentionableNotFound":"Unable to find user or role!",
- "channelType":"Invalid channel type!",
- "notInGuild":"This option requires you to be in a server!"
+ "stringRegex":"The value does not match the required pattern.",
+ "stringMinLength":"The value must be at least {0} characters long.",
+ "stringMaxLength":"The value must be at most {0} characters long.",
+ "numberInvalid":"Invalid number provided.",
+ "numberMin":"The number must be at least {0}.",
+ "numberMax":"The number must be at most {0}.",
+ "numberDecimal":"Decimals are not allowed.",
+ "numberNegative":"Negative numbers are not allowed.",
+ "numberPositive":"Positive numbers are not allowed.",
+ "numberZero":"Zero is not allowed.",
+ "channelNotFound":"Channel not found.",
+ "userNotFound":"User not found.",
+ "roleNotFound":"Role not found.",
+ "memberNotFound":"Member not found.",
+ "mentionableNotFound":"User or role not found.",
+ "channelType":"Invalid channel type.",
+ "notInGuild":"This option can only be used in a server."
},
"permissions":{
- "developer":"You need to be the developer of the bot.",
- "owner":"You need to be the server owner.",
- "admin":"You need to be a server admin.",
- "moderator":"You need to be a moderator.",
- "support":"You need to be in the support team.",
- "member":"You need to be a member.",
- "discord-administrator":"You need to have the `ADMINISTRATOR` permission."
+ "developer":"This action is restricted to the bot developer.",
+ "owner":"You must be the server owner to use this.",
+ "admin":"You must have administrator permissions to use this.",
+ "moderator":"You must be a moderator to use this.",
+ "support":"You must be part of the support team to use this.",
+ "member":"You must be a server member to use this.",
+ "discord-administrator":"You must have the `ADMINISTRATOR` permission."
},
"actionInvalid":{
- "close":"Ticket is already closed!",
- "reopen":"Ticket is not closed yet!",
- "claim":"Ticket is already claimed!",
- "unclaim":"Ticket is not claimed yet!",
- "pin":"Ticket is already pinned!",
- "unpin":"Ticket is not pinned yet!",
- "add":"This user is already able to access the ticket!",
- "remove":"Unable to remove this user from the ticket!"
+ "close":"This ticket is already closed.",
+ "reopen":"This ticket is not closed.",
+ "claim":"This ticket is already claimed.",
+ "unclaim":"This ticket is not claimed.",
+ "pin":"This ticket is already pinned.",
+ "unpin":"This ticket is not pinned.",
+ "add":"This user already has access to this ticket.",
+ "remove":"This user does not have access to this ticket."
}
},
"params":{
@@ -432,107 +432,107 @@
}
},
"commands":{
- "reason":"Specify an optional reason that will be visible in logs.",
- "help":"Get a list of all the available commands.",
- "panel":"Spawn a message with a dropdown or buttons (for ticket creation).",
- "panelId":"The identifier of the panel that you want to spawn.",
- "panelAutoUpdate":"Do you want this panel to automatically update when edited?",
- "ticket":"Instantly create a ticket.",
- "ticketId":"The identifier of the ticket that you want to create.",
- "close":"Close a ticket.",
- "delete":"Delete a ticket.",
- "deleteNoTranscript":"Delete this ticket without creating a transcript.",
- "reopen":"Reopen a ticket.",
- "claim":"Claim a ticket.",
- "claimUser":"Claim this ticket to someone else instead of yourself.",
- "unclaim":"Unclaim a ticket.",
- "pin":"Pin a ticket.",
- "unpin":"Unpin a ticket.",
+ "reason":"Optional reason shown in logs.",
+ "help":"Display all available commands.",
+ "panel":"Create a ticket panel (buttons or dropdown).",
+ "panelId":"ID of the panel to spawn.",
+ "panelAutoUpdate":"Automatically update this panel when edited.",
+ "ticket":"Create a ticket instantly.",
+ "ticketId":"ID of the ticket to create.",
+ "close":"Close this ticket.",
+ "delete":"Delete this ticket.",
+ "deleteNoTranscript":"Delete ticket without saving a transcript.",
+ "reopen":"Reopen a closed ticket.",
+ "claim":"Claim this ticket.",
+ "claimUser":"Claim the ticket for another user.",
+ "unclaim":"Unclaim this ticket.",
+ "pin":"Pin this ticket.",
+ "unpin":"Unpin this ticket.",
- "move":"Move a ticket.",
- "moveId":"The identifier of the option that you want to move to.",
- "rename":"Rename a ticket.",
- "renameName":"The new name for this ticket.",
- "add":"Add a user to a ticket.",
- "addUser":"The user to add.",
- "remove":"Remove a user from a ticket.",
- "removeUser":"The user to remove.",
+ "move":"Move ticket to another option.",
+ "moveId":"Target option ID.",
+ "rename":"Rename this ticket.",
+ "renameName":"New name for the ticket.",
+ "add":"Add a user to this ticket.",
+ "addUser":"User to add.",
+ "remove":"Remove a user from this ticket.",
+ "removeUser":"User to remove.",
- "blacklist":"Manage the ticket blacklist.",
- "blacklistView":"View a list of the current blacklist.",
+ "blacklist":"Manage the blacklist.",
+ "blacklistView":"View all blacklisted users.",
"blacklistAdd":"Add a user to the blacklist.",
"blacklistRemove":"Remove a user from the blacklist.",
- "blacklistGet":"Get the details from a blacklisted user.",
- "blacklistGetUser":"The user to get details from.",
- "stats":"View statistics from the bot, a member or a ticket.",
- "statsReset":"Reset all the stats of the bot (and start counting from zero).",
- "statsGlobal":"View the global stats.",
- "statsUser":"View the stats from a user in the server.",
- "statsUserUser":"The user to view.",
- "statsTicket":"View the stats of a ticket in the server.",
- "statsTicketTicket":"The ticket to view.",
+ "blacklistGet":"View blacklist entry details.",
+ "blacklistGetUser":"User to look up.",
+ "stats":"View bot, user or ticket statistics.",
+ "statsReset":"Reset all bot statistics.",
+ "statsGlobal":"View global bot statistics.",
+ "statsUser":"View a user's statistics.",
+ "statsUserUser":"User to view.",
+ "statsTicket":"View ticket statistics.",
+ "statsTicketTicket":"Ticket to view.",
- "clear":"Delete multiple tickets at the same time.",
- "clearFilter":"The filter for clearing tickets.",
+ "clear":"Delete multiple tickets at once.",
+ "clearFilter":"Filter used when clearing tickets.",
"clearFilters":{
- "all":"All",
- "open":"Open",
- "close":"Closed",
- "claim":"Claimed",
- "unclaim":"Unclaimed",
- "pin":"Pinned",
- "unpin":"Unpinned",
- "autoclose":"Autoclosed"
+ "all":"All tickets",
+ "open":"Open tickets",
+ "close":"Closed tickets",
+ "claim":"Claimed tickets",
+ "unclaim":"Unclaimed tickets",
+ "pin":"Pinned tickets",
+ "unpin":"Unpinned tickets",
+ "autoclose":"Autoclosed tickets"
},
- "autoclose":"Manage autoclose in a ticket.",
- "autocloseDisable":"Disable autoclose in this ticket.",
- "autocloseEnable":"Enable autoclose in this ticket.",
- "autocloseEnableTime":"The amount of hours this ticket needs to be inactive to close it.",
- "autodelete":"Manage autodelete in a ticket.",
- "autodeleteDisable":"Disable autodelete in this ticket.",
- "autodeleteEnable":"Enable autodelete in this ticket.",
- "autodeleteEnableTime":"The amount of days this ticket needs to be inactive to delete it.",
+ "autoclose":"Manage ticket autoclose.",
+ "autocloseDisable":"Disable autoclose.",
+ "autocloseEnable":"Enable autoclose.",
+ "autocloseEnableTime":"Hours of inactivity before closing.",
+ "autodelete":"Manage ticket autodelete.",
+ "autodeleteDisable":"Disable autodelete.",
+ "autodeleteEnable":"Enable autodelete.",
+ "autodeleteEnableTime":"Days of inactivity before deletion.",
- "topic":"Manage the topic of the ticket channel.",
- "topicSet":"Set the topic of the ticket channel.",
- "topicValue":"The new topic of the channel.",
- "topicList":"Get a list of all tickets with their topic and stats.",
- "priority":"Manage the priority of the ticket.",
- "prioritySet":"Set the priority of the ticket.",
- "priorityValue":"The priority of the channel.",
- "priorityGet":"Get the priority of the ticket.",
- "priorityList":"Get a list of all tickets with their priority status.",
- "transfer":"Transfer the ticket ownership from one user to another.",
- "transferUser":"The user to transfer to."
+ "topic":"Manage ticket channel topic.",
+ "topicSet":"Set the ticket channel topic.",
+ "topicValue":"New channel topic text.",
+ "topicList":"List all ticket channel topics.",
+ "priority":"Manage ticket priority.",
+ "prioritySet":"Set ticket priority.",
+ "priorityValue":"Priority level.",
+ "priorityGet":"View ticket priority.",
+ "priorityList":"List all ticket priorities.",
+ "transfer":"Transfer ticket ownership.",
+ "transferUser":"User to transfer to."
},
"helpMenu":{
- "help":"Get a list of all the available commands.",
- "ticket":"Instantly create a ticket.",
- "close":"Close a ticket, this disables writing in this channel.",
- "delete":"Delete a ticket, this creates a transcript when enabled.",
- "reopen":"Reopen a ticket, this enables writing in this channel again.",
- "pin":"Pin a ticket. This will move the ticket to the top and will add a '๐' emoij to the name.",
- "unpin":"Unpin a ticket. The ticket will stay on it's position but will lose the '๐' emoij.",
- "move":"Move a ticket. This will change the type of this ticket.",
- "rename":"Rename a ticket. This will change the channel name of this ticket.",
- "claim":"Claim a ticket. With this, you can let your team know you are handling this ticket.",
- "unclaim":"Unclaim a ticket. With this, you can let your team know that this ticket is free again.",
- "add":"Add a user to a ticket. This will allow the user to read & write in this ticket.",
- "remove":"Remove a user from a ticket. This will remove the ability to read & write for a user in this ticket.",
- "panel":"Spawn a message with a dropdown or buttons (for ticket creation).",
- "blacklistView":"View a list of the current blacklist.",
+ "help":"View all available commands.",
+ "ticket":"Create a ticket instantly.",
+ "close":"Close this ticket and disable messaging in the channel.",
+ "delete":"Delete this ticket (creates a transcript if enabled).",
+ "reopen":"Reopen a closed ticket and restore messaging.",
+ "pin":"Pin this ticket and move it to the top with '๐'.",
+ "unpin":"Unpin this ticket and remove the '๐' emoji.",
+ "move":"Move this ticket to a different option or ticket type.",
+ "rename":"Rename this ticket channel.",
+ "claim":"Claim this ticket to show you are handling it.",
+ "unclaim":"Unclaim this ticket to mark it as available.",
+ "add":"Add a user to this ticket.",
+ "remove":"Remove a user's access from this ticket.",
+ "panel":"Create a ticket panel with buttons or a dropdown.",
+ "blacklistView":"View all blacklisted users.",
"blacklistAdd":"Add a user to the blacklist.",
"blacklistRemove":"Remove a user from the blacklist.",
- "blacklistGet":"Get the details from a blacklisted user.",
- "statsGlobal":"View the global stats.",
- "statsTicket":"View the stats of a ticket in the server.",
- "statsUser":"View the stats from a user in the server.",
- "statsReset":"Reset all the stats of the bot (and start counting from zero).",
- "autocloseDisable":"Disable autoclose in this ticket.",
- "autocloseEnable":"Enable autoclose in this ticket.",
- "autodeleteDisable":"Disable autodelete in this ticket.",
- "autodeleteEnable":"Enable autodelete in this ticket.",
+ "blacklistGet":"View details of a blacklisted user.",
+ "statsGlobal":"View global bot statistics.",
+ "statsTicket":"View statistics for a ticket.",
+ "statsUser":"View statistics for a user.",
+ "statsReset":"Reset all bot statistics.",
+ "autocloseDisable":"Disable autoclose for this ticket.",
+ "autocloseEnable":"Enable autoclose for this ticket.",
+ "autodeleteDisable":"Disable autodelete for this ticket.",
+ "autodeleteEnable":"Enable autodelete for this ticket.",
"categories":{
"general":"General Commands",
"basicTicket":"Basic Ticket Commands",
@@ -545,10 +545,10 @@
},
"stats":{
"scopes":{
- "global":"Global Stats",
- "system":"System Stats",
- "user":"User Stats",
- "ticket":"Ticket Stats",
+ "global":"Global Statistics",
+ "system":"System Statistics",
+ "user":"User Statistics",
+ "ticket":"Ticket Statistics",
"participants":"Participants",
"messages":"Messages"
},
@@ -592,9 +592,9 @@
}
},
"panel":{
- "selectTicket":"Select your ticket",
- "selectRole":"Select your role",
- "selectOption":"Select your option"
+ "selectTicket":"Select a ticket",
+ "selectRole":"Select a role",
+ "selectOption":"Select an option"
},
"priorities":{
"urgent":"Urgent",
diff --git a/languages/czech.json b/languages/czech.json
index ef4a93a..03b8bc3 100644
--- a/languages/czech.json
+++ b/languages/czech.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["spyeye_"],
"lastedited":"16/02/2026",
"language":"Czech",
diff --git a/languages/danish.json b/languages/danish.json
index 4f93fed..ab42fd0 100644
--- a/languages/danish.json
+++ b/languages/danish.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["the_gamer"],
"lastedited":"16/02/2026",
"language":"Danish",
diff --git a/languages/dutch.json b/languages/dutch.json
index f13ddfc..9c19866 100644
--- a/languages/dutch.json
+++ b/languages/dutch.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["DJj123dj"],
"lastedited":"16/02/2026",
"language":"Dutch",
diff --git a/languages/english.json b/languages/english.json
index a833cf8..7244893 100644
--- a/languages/english.json
+++ b/languages/english.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["DJj123dj"],
"lastedited":"16/02/2026",
"language":"English",
@@ -13,94 +13,94 @@
"typeWarning":"[WARNING]",
"typeInfo":"[INFO]",
"headerConfigChecker":"CONFIG CHECKER",
- "headerDescription":"check for errors in your config files!",
- "footerError":"the bot won't start until all {0}'s are fixed!",
- "footerWarning":"it's recommended to fix all {0}'s before starting!",
+ "headerDescription":"Validating config files...",
+ "footerError":"The bot will not start until all {0}'s are resolved.",
+ "footerWarning":"The bot may behave unexpectedly until all {0}'s are resolved.",
"footerSupport":"SUPPORT: {0} - DOCS: {1}",
- "compactInformation":"use {0} for more information!",
+ "compactInformation":"Use {0} for a detailed config report.",
"dataPath":"path",
"dataDocs":"docs",
"dataMessages":"message"
},
"messages":{
- "stringTooShort":"This string can't be shorter than {0} characters!",
- "stringTooLong":"This string can't be longer than {0} characters!",
- "stringLengthInvalid":"This string needs to be {0} characters long!",
- "stringStartsWith":"This string needs to start with {0}!",
- "stringEndsWith":"This string needs to end with {0}!",
- "stringContains":"This string needs to contain {0}!",
- "stringChoices":"This string can only be one of the following values: {0}!",
- "stringRegex":"This string is invalid!",
- "stringInvertedContains":"This string is not allowed to contain {0}!",
- "stringLowercase":"This string must be written in lowercase only!",
- "stringUppercase":"This string must be written in uppercase only!",
- "stringSpecialCharacters":"This string is not allowed to contain any special characters! (a-z, 0-9 & space only)",
- "stringNoSpaces":"This string is not allowed to contain spaces!",
- "stringCapitalWord":"It's recommended that each word in this string starts with a capital letter!",
- "stringCapitalSentence":"It looks like some sentences in this string don't start with a capital letter!",
- "stringPunctuation":"It looks like the sentence in this string doesn't end with a punctuation mark!",
+ "stringTooShort":"Text must be at least {0} characters long",
+ "stringTooLong":"Text must be no longer than {0} characters",
+ "stringLengthInvalid":"Text must be exactly {0} characters long",
+ "stringStartsWith":"Text must start with {0}",
+ "stringEndsWith":"Text must end with {0}",
+ "stringContains":"Text must contain {0}",
+ "stringChoices":"Text must be one of the following: {0}",
+ "stringRegex":"Text does not match the required format",
+ "stringInvertedContains":"Text must not contain {0}",
+ "stringLowercase":"Text must be entirely lowercase",
+ "stringUppercase":"Text must be entirely uppercase",
+ "stringSpecialCharacters":"Text must only contain letters (aโz), numbers (0โ9), and spaces",
+ "stringNoSpaces":"Text must not contain spaces",
+ "stringCapitalWord":"Each word in this value should start with a capital letter",
+ "stringCapitalSentence":"One or more sentences in this value do not start with a capital letter",
+ "stringPunctuation":"The sentence in this value does not end with a punctuation mark",
- "numberTooShort":"This number can't be shorter than {0} characters!",
- "numberTooLong":"This number can't be longer than {0} characters!",
- "numberLengthInvalid":"This number needs to be {0} characters long!",
- "numberTooSmall":"This number needs to be at least {0}!",
- "numberTooLarge":"This number needs to be at most {0}!",
- "numberNotEqual":"This number needs to be {0}!",
- "numberStep":"This number needs to be a multiple of {0}!",
- "numberStepOffset":"This number needs to be a multiple of {0} starting with {1}!",
- "numberStartsWith":"This number needs to start with {0}!",
- "numberEndsWith":"This number needs to end with {0}!",
- "numberContains":"This number needs to contain {0}!",
- "numberChoices":"This number can only be one of the following values: {0}!",
- "numberFloat":"This number can't be a decimal!",
- "numberNegative":"This number can't be negative!",
- "numberPositive":"This number can't be positive!",
- "numberZero":"This number can't be zero!",
- "numberNan":"This number can't be NaN (Not A Number)!",
- "numberInvertedContains":"This number is not allowed to contain {0}!",
+ "numberTooShort":"Number must be at least {0} digits long",
+ "numberTooLong":"Number must be no longer than {0} digits",
+ "numberLengthInvalid":"Number must be exactly {0} digits long",
+ "numberTooSmall":"Number must be at least {0}",
+ "numberTooLarge":"Number must be at most {0}",
+ "numberNotEqual":"Number must be exactly {0}",
+ "numberStep":"Number must be a multiple of {0}",
+ "numberStepOffset":"Number must be a multiple of {0}, starting from {1}",
+ "numberStartsWith":"Number must start with {0}",
+ "numberEndsWith":"Number must end with {0}",
+ "numberContains":"Number must contain {0}",
+ "numberChoices":"Number must be one of the following: {0}",
+ "numberFloat":"Number must be a whole number",
+ "numberNegative":"Number must be a positive number",
+ "numberPositive":"Number must be a negative number",
+ "numberZero":"Number must not be zero",
+ "numberNan":"Number must be a valid number",
+ "numberInvertedContains":"Number must not contain {0}",
- "booleanTrue":"This boolean can't be true!",
- "booleanFalse":"This boolean can't be false!",
+ "booleanTrue":"Boolean must be false",
+ "booleanFalse":"Boolean must be true",
+
+ "arrayEmptyDisabled":"List must not be empty",
+ "arrayEmptyRequired":"List must be empty",
+ "arrayTooShort":"List must have at least {0} items",
+ "arrayTooLong":"List must have at most {0} items",
+ "arrayLengthInvalid":"List must have exactly {0} items",
+ "arrayInvalidTypes":"List may only contain the following types: {0}",
+ "arrayDouble":"List must not contain duplicate values",
+
+ "discordInvalidId":"Invalid Discord {0} ID",
+ "discordInvalidIdOptions":"Invalid Discord {0} ID. Alternatively, use one of the following: {1}",
+ "discordInvalidToken":"Invalid Discord token",
+ "colorInvalid":"Invalid hex color",
+ "emojiTooShort":"Value must contain at least {0} emoji",
+ "emojiTooLong":"Value must contain at most {0} emoji",
+ "emojiCustom":"Custom Discord emojis are not allowed here",
+ "emojiInvalid":"Invalid emoji",
+ "urlInvalid":"Invalid URL",
+ "urlInvalidHttp":"URL must use the https:// protocol",
+ "urlInvalidProtocol":"URL must use the http:// or https:// protocol",
+ "urlInvalidHostname":"URL hostname is not allowed",
+ "urlInvalidExtension":"Invalid URL extension. Allowed extensions: {0}",
+ "urlInvalidPath":"Invalid URL path",
+ "idNotUnique":"This ID is already in use. Please choose a unique ID",
+ "idNonExistent":"ID {0} does not exist",
+
+ "invalidType":"Property must be of type: {0}",
+ "propertyMissing":"Required property {0} is missing from the object",
+ "propertyOptional":"Property {0} is optional in the object",
+ "objectDisabled":"This object is disabled. Enable it using {0}",
+ "nullInvalid":"Property must not be null",
+ "switchInvalidType":"Value must be one of the following types: {0}",
+ "objectSwitchInvalid":"Object must be one of the following types: {0}",
- "arrayEmptyDisabled":"This array isn't allowed to be empty!",
- "arrayEmptyRequired":"This array is required to be empty!",
- "arrayTooShort":"This array needs to have a length of at least {0}!",
- "arrayTooLong":"This array needs to have a length of at most {0}!",
- "arrayLengthInvalid":"This array needs to have a length of {0}!",
- "arrayInvalidTypes":"This array can only contain the following types: {0}!",
- "arrayDouble":"This array doesn't allow the same value twice!",
-
- "discordInvalidId":"This is an invalid discord {0} id!",
- "discordInvalidIdOptions":"This is an invalid discord {0} id! You can also use one of these: {1}!",
- "discordInvalidToken":"This is an invalid discord token (syntactically)!",
- "colorInvalid":"This is an invalid hex color!",
- "emojiTooShort":"This string needs to have at least {0} emoji's!",
- "emojiTooLong":"This string needs to have at most {0} emoji's!",
- "emojiCustom":"This emoji can't be a custom discord emoji!",
- "emojiInvalid":"This is an invalid emoji!",
- "urlInvalid":"This url is invalid!",
- "urlInvalidHttp":"This url can only use the https:// protocol!",
- "urlInvalidProtocol":"This url can only use the http:// & https:// protocols!",
- "urlInvalidHostname":"This url has a disallowed hostname!",
- "urlInvalidExtension":"This url has an invalid extension! Choose between: {0}!",
- "urlInvalidPath":"This url has an invalid path!",
- "idNotUnique":"This id isn't unique, use another id instead!",
- "idNonExistent":"The id {0} doesn't exist!",
-
- "invalidType":"This property needs to be the type: {0}!",
- "propertyMissing":"The property {0} is missing from this object!",
- "propertyOptional":"The property {0} is optional in this object!",
- "objectDisabled":"This object is disabled, enable it using {0}!",
- "nullInvalid":"This property can't be null!",
- "switchInvalidType":"This needs to be one of the following types: {0}!",
- "objectSwitchInvalid":"This object needs to be one of the following types: {0}!",
-
- "invalidLanguage":"This is an invalid language!",
- "invalidButton":"This button needs to have at least an {0} or {1}!",
- "unusedOption":"The option {0} isn't used anywhere!",
- "unusedQuestion":"The question {0} isn't used anywhere!",
- "dropdownOption":"A panel with dropdown enabled can only contain options of the 'ticket' type!",
- "customInvalidVersion":"The version specified in your config does not match! Make sure you have updated the config to the latest version!"
+ "invalidLanguage":"Invalid language",
+ "invalidButton":"Button must have at least an {0} or {1}",
+ "unusedOption":"Option {0} is not used anywhere",
+ "unusedQuestion":"Question {0} is not used anywhere",
+ "dropdownOption":"Panels with dropdown enabled may only contain options of the 'ticket' type",
+ "customInvalidVersion":"Config version mismatch. Make sure to update your config to the latest version"
}
},
"actions":{
@@ -159,118 +159,118 @@
"transfer":"Ticket Transferred"
},
"descriptions":{
- "create":"Your ticket has been created. Click the button below to access it!",
- "close":"The ticket has been closed successfully!",
- "delete":"The ticket has been deleted successfully!",
- "reopen":"The ticket has been reopened successfully!",
- "claim":"The ticket has been claimed successfully!",
- "unclaim":"The ticket has been unclaimed successfully!",
- "pin":"The ticket has been pinned successfully!",
- "unpin":"The ticket has been unpinned successfully!",
- "rename":"The ticket has been renamed to {0} successfully!",
- "move":"The ticket has been moved to {0} successfully!",
- "add":"{0} has been added to the ticket successfully!",
- "remove":"{0} has been removed from the ticket successfully!",
+ "create":"Your ticket is ready. Click the button below to view and continue.",
+ "close":"The ticket has been closed.",
+ "delete":"The ticket has been deleted.",
+ "reopen":"The ticket has been reopened.",
+ "claim":"The ticket has been claimed.",
+ "unclaim":"The ticket has been unclaimed.",
+ "pin":"The ticket has been pinned.",
+ "unpin":"The ticket has been unpinned.",
+ "rename":"The ticket has been renamed to {0}.",
+ "move":"The ticket has been moved to {0}.",
+ "add":"{0} has been added to the ticket.",
+ "remove":"{0} has been removed from the ticket.",
"helpExplanation":"`` => required parameter\n`[name]` => optional parameter",
- "statsReset":"The bot stats have been reset successfully!",
- "statsError":"Unable to view ticket stats!\n{0} is not a ticket!",
- "blacklistAdd":"{0} has been blacklisted successfully!",
- "blacklistRemove":"{0} has been released successfully!",
- "blacklistGetSuccess":"{0} is currently blacklisted!",
- "blacklistGetEmpty":"{0} is currently not blacklisted!",
- "blacklistViewEmpty":"No-one has been blacklisted yet!",
- "blacklistViewTip":"Use \"/blacklist add\" to blacklist a user!",
- "clearVerify":"Are you sure you want to delete multiple tickets?\nThis action can't be undone!",
- "clearReady":"{0} tickets have been deleted successfully!",
- "rolesEmpty":"No roles have been updated!",
+ "statsReset":"The bot statistics have been reset.",
+ "statsError":"Unable to retrieve ticket statistics.\n{0} is not a valid ticket.",
+ "blacklistAdd":"{0} has been blacklisted.",
+ "blacklistRemove":"{0} has been released.",
+ "blacklistGetSuccess":"{0} is blacklisted!",
+ "blacklistGetEmpty":"{0} is not blacklisted!",
+ "blacklistViewEmpty":"No users have been blacklisted yet.",
+ "blacklistViewTip":"Use \"/blacklist add\" to add a user to the blacklist.",
+ "clearVerify":"Are you sure you want to delete multiple tickets?\nThis action cannot be undone.",
+ "clearReady":"{0} ticket(s) have been deleted.",
+ "rolesEmpty":"No roles were modified.",
- "autocloseLeave":"This ticket has been autoclosed because the creator left the server!",
- "autocloseTimeout":"This ticket has been autoclosed because it has been inactive for more than `{0}h`!",
- "autodeleteLeave":"This ticket has been autodeleted because the creator left the server!",
- "autodeleteTimeout":"This ticket has been autodeleted because it has been inactive for more than `{0} days`!",
- "autocloseEnabled":"Autoclose has been enabled in this ticket!\nIt will be closed when it is inactive for more than `{0}h`!",
- "autocloseDisabled":"Autoclose has been disabled in this ticket!\nIt won't be closed automatically anymore!",
- "autodeleteEnabled":"Autodelete has been enabled in this ticket!\nIt will be deleted when it is inactive for more than `{0} days`!",
- "autodeleteDisabled":"Autodelete has been disabled in this ticket!\nIt won't be deleted automatically anymore!",
+ "autocloseLeave":"This ticket was automatically closed because its creator left the server.",
+ "autocloseTimeout":"This ticket was automatically closed due to inactivity exceeding `{0}h`.",
+ "autodeleteLeave":"This ticket was automatically deleted because its creator left the server.",
+ "autodeleteTimeout":"This ticket was automatically deleted due to inactivity exceeding `{0} days`.",
+ "autocloseEnabled":"Autoclose has been enabled for this ticket.\nIt will close after `{0}h` of inactivity.",
+ "autocloseDisabled":"Autoclose has been disabled for this ticket.\nThis ticket will no longer close automatically.",
+ "autodeleteEnabled":"Autodelete has been enabled for this ticket.\nIt will be deleted after `{0} days` of inactivity.",
+ "autodeleteDisabled":"Autodelete has been disabled for this ticket.\nThis ticket will no longer be deleted automatically.",
- "ticketMessageLimit":"You can only create {0} ticket(s) at the same time!",
- "ticketMessageAutoclose":"This ticket will be autoclosed when inactive for {0}h!",
- "ticketMessageAutodelete":"This ticket will be autodeleted when inactive for {0} days!",
- "panelReady":"The panel is available in the followup message!\nThis message can now be deleted!",
+ "ticketMessageLimit":"You can only have {0} active ticket(s) at a time.",
+ "ticketMessageAutoclose":"This ticket will automatically close after `{0}h` of inactivity.",
+ "ticketMessageAutodelete":"This ticket will automatically be deleted after `{0} days` of inactivity.",
+ "panelReady":"The panel has been sent in the follow-up message.\nYou may now delete this message.",
- "topicSet":"The channel topic has been changed by {0} successfully!",
- "prioritySet":"The ticket priority has been changed to {0} by {1} successfully!",
- "priorityGet":"The current priority of this ticket is {0}.",
- "transfer":"The ticket ownership has been transferred from {0} to {1} by {2} successfully!"
+ "topicSet":"The channel topic has been changed by {0}.",
+ "prioritySet":"The ticket priority has been changed to {0} by {1}.",
+ "priorityGet":"The priority of this ticket is {0}.",
+ "transfer":"The ticket ownership has been transferred from {0} to {1} by {2}."
},
"modal":{
- "closePlaceholder":"Why did you close this ticket?",
- "deletePlaceholder":"Why did you delete this ticket?",
- "reopenPlaceholder":"Why did you reopen this ticket?",
- "claimPlaceholder":"Why did you claim this ticket?",
- "unclaimPlaceholder":"Why did you unclaim this ticket?",
- "pinPlaceholder":"Why did you pin this ticket?",
- "unpinPlaceholder":"Why did you unpin this ticket?"
+ "closePlaceholder":"Why would you like to close this ticket?",
+ "deletePlaceholder":"Why would you like to delete this ticket?",
+ "reopenPlaceholder":"Why would you like to reopen this ticket?",
+ "claimPlaceholder":"Why would you like to claim this ticket?",
+ "unclaimPlaceholder":"Why would you like to unclaim this ticket?",
+ "pinPlaceholder":"Why would you like to pin this ticket?",
+ "unpinPlaceholder":"Why would you like to unpin this ticket?"
},
"logs":{
- "createLog":"A new ticket got created by {0}!",
- "closeLog":"This ticket has been closed by {0}!",
- "closeDm":"Your ticket has been closed in our server!",
- "deleteLog":"This ticket has been deleted by {0}!",
- "deleteDm":"Your ticket has been deleted in our server!",
- "reopenLog":"This ticket has been reopened by {0}!",
- "reopenDm":"Your ticket has been reopened in our server!",
- "claimLog":"This ticket has been claimed by {0}!",
- "claimDm":"Your ticket has been claimed in our server!",
- "unclaimLog":"This ticket has been unclaimed by {0}!",
- "unclaimDm":"Your ticket has been unclaimed in our server!",
- "pinLog":"This ticket has been pinned by {0}!",
- "pinDm":"Your ticket has been pinned in our server!",
- "unpinLog":"This ticket has been unpinned by {0}!",
- "unpinDm":"Your ticket has been unpinned in our server!",
- "renameLog":"This ticket has been renamed to {0} by {1}!",
- "renameDm":"Your ticket has been renamed to {0} in our server!",
- "moveLog":"This ticket has been moved to {0} by {1}!",
- "moveDm":"Your ticket has been moved to {0} in our server!",
- "addLog":"{0} has been added to this ticket by {1}!",
- "addDm":"{0} has been added to your ticket in our server!",
- "removeLog":"{0} has been removed from this ticket by {1}!",
- "removeDm":"{0} has been removed from your ticket in our server!",
+ "createLog":"A new ticket got created by {0}.",
+ "closeLog":"This ticket has been closed by {0}.",
+ "closeDm":"Your ticket has been closed.",
+ "deleteLog":"This ticket has been deleted by {0}.",
+ "deleteDm":"Your ticket has been deleted.",
+ "reopenLog":"This ticket has been reopened by {0}.",
+ "reopenDm":"Your ticket has been reopened.",
+ "claimLog":"This ticket has been claimed by {0}.",
+ "claimDm":"Your ticket has been claimed.",
+ "unclaimLog":"This ticket has been unclaimed by {0}.",
+ "unclaimDm":"Your ticket has been unclaimed.",
+ "pinLog":"This ticket has been pinned by {0}.",
+ "pinDm":"Your ticket has been pinned.",
+ "unpinLog":"This ticket has been unpinned by {0}.",
+ "unpinDm":"Your ticket has been unpinned.",
+ "renameLog":"This ticket has been renamed to {0} by {1}.",
+ "renameDm":"Your ticket has been renamed to {0}.",
+ "moveLog":"This ticket has been moved to {0} by {1}.",
+ "moveDm":"Your ticket has been moved to {0}.",
+ "addLog":"{0} has been added to this ticket by {1}.",
+ "addDm":"{0} has been added to your ticket.",
+ "removeLog":"{0} has been removed from this ticket by {1}.",
+ "removeDm":"{0} has been removed from your ticket.",
- "blacklistAddLog":"{0} was blacklisted by {1}!",
- "blacklistRemoveLog":"{0} was removed from the blacklist by {1}!",
- "blacklistAddDm":"You have been blacklisted in our server!\nFrom now on, you are unable to create a ticket!",
- "blacklistRemoveDm":"You have been removed from the blacklist in our server!\nNow you can create tickets again!",
- "clearLog":"{0} tickets have been deleted by {1}!",
+ "blacklistAddLog":"{0} has been blacklisted by {1}.",
+ "blacklistRemoveLog":"{0} has been removed from the blacklist by {1}.",
+ "blacklistAddDm":"You have been blacklisted from this server.\nYou are no longer able to create tickets.",
+ "blacklistRemoveDm":"You have been removed from the blacklist.\nYou can now create tickets again.",
+ "clearLog":"{0} ticket(s) have been deleted by {1}.",
- "transferLog":"The ownership of this ticket has been transferred from {0} to {1} by {2}!",
- "transferDm":"The ownership of your ticket has been transferred from {0} to {1} in our server!",
- "prioritySetLog":"The priority of this ticket has been changed to {0} by {1}!",
- "prioritySetDm":"The priority of your ticket has been changed to {0} in our server!",
- "roleUpdateLog":"{0} has updated their roles!",
- "roleUpdateDm":"Your roles in our server have been updated!"
+ "transferLog":"Ticket ownership has been transferred from {0} to {1} by {2}.",
+ "transferDm":"Ownership of your ticket has been transferred from {0} to {1}.",
+ "prioritySetLog":"The priority of this ticket has been set to {0} by {1}.",
+ "prioritySetDm":"The priority of your ticket has been set to {0}.",
+ "roleUpdateLog":"{0} has modified their roles.",
+ "roleUpdateDm":"Your roles have been modified."
}
},
"transcripts":{
"success":{
"visit":"Visit Transcript",
"ready":"Transcript Created",
- "textFileDescription":"This is the text transcript of a deleted ticket!",
- "htmlProgress":"Please wait while this html transcript is getting processed...",
-
- "createdChannel":"A new {0} transcript has been created in the server!",
- "createdCreator":"A new {0} transcript has been created for one of your tickets!",
- "createdParticipant":"A new {0} transcript has been created in one of the tickets you participated in!",
- "createdActiveAdmin":"A new {0} transcript has been created in one of the tickets you participated as admin!",
- "createdEveryAdmin":"A new {0} transcript has been created in one of the tickets you were admin in!",
- "createdOther":"A new {0} transcript has been created!"
+ "textFileDescription":"This is a text transcript of a deleted ticket.",
+ "htmlProgress":"Please wait while the HTML transcript is being generated...",
+
+ "createdChannel":"A new {0} transcript has been created in the server.",
+ "createdCreator":"A new {0} transcript has been created for one of your tickets.",
+ "createdParticipant":"A new {0} transcript has been created for a ticket you participated in.",
+ "createdActiveAdmin":"A new {0} transcript has been created for a ticket you participated in as an admin.",
+ "createdEveryAdmin":"A new {0} transcript has been created for a ticket you managed as an admin.",
+ "createdOther":"A new {0} transcript has been created."
},
"errors":{
"retry":"Retry",
"continue":"Delete Without Transcript",
"backup":"Create Backup Transcript",
- "error":"Something went wrong while trying to create the transcript.\nWhat would you like to do?\n\nThis ticket won't be deleted until you click one of these buttons.",
+ "error":"Something went wrong while creating the transcript.\nWhat would you like to do?\n\nThis ticket will not be deleted until you select one of the options below.",
"title":"Transcript Error"
},
"text":{
@@ -279,7 +279,7 @@
"fileTitle":"FILE",
"fieldsTitle":"FIELDS",
"reactionsTitle":"REACTIONS",
- "statsTitle":"STATS",
+ "statsTitle":"STATISTICS",
"emptyContent":"",
"noTitle":"",
"noDesc":""
@@ -302,68 +302,68 @@
"permissionError":"Permission Error"
},
"descriptions":{
- "askForInfo":"Contact the owner of this bot for more info!",
- "askForInfoResolve":"Contact the bot owner of this bot if this issue doesn't resolve after a few tries.",
- "internalError":"Failed to respond to this {0} due to an internal error!",
- "optionMissing":"A required parameter is missing in this command!",
- "optionInvalid":"A parameter in this command is invalid!",
- "optionInvalidChoose":"Choose between",
- "unknownCommand":"Try visiting the help menu for more info!",
- "noPermissions":"You are not allowed to use this {0}!",
- "noPermissionsList":"Required Permissions: (one of them)",
- "noPermissionsCooldown":"You are not allowed to use this {0} because you have a cooldown!",
- "noPermissionsBlacklist":"You are not allowed to use this {0} because you have been blacklisted!",
- "noPermissionsLimitGlobal":"You are not allowed to create a ticket because the server reached the max tickets limit!",
- "noPermissionsLimitGlobalUser":"You are not allowed to create a ticket because you reached the max tickets limit!",
- "noPermissionsLimitOption":"You are not allowed to create a ticket because the server reached the max tickets limit for this option!",
- "noPermissionsLimitOptionUser":"You are not allowed to create a ticket because you reached the max tickets limit for this option!",
- "unknownTicket":"Try this command again in a valid ticket!",
- "deprecatedTicket":"The current channel is not a valid ticket! It might have been a ticket from an old Open Ticket version!",
- "notInGuild":"This {0} doesn't work in DM! Please try it again in a server!",
- "channelRename":"Due to discord ratelimits, it's currently impossible for the bot to rename the channel. The channel will automatically be renamed over 10 minutes if the bot isn't rebooted.",
- "channelRenameSource":"The source of this error is: {0}",
- "busy":"Unable to use this {0}!\nThe ticket is currently being processed by the bot.\n\nPlease try again in a few seconds!",
- "closeBeforeMessage":"This ticket cannot be closed/deleted before a message has been sent by a user.",
- "closeBeforeAdminMessage":"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",
- "unableToCreateTicket":"You are unable to create a ticket."
+ "askForInfo":"Please contact the bot owner for more information.",
+ "askForInfoResolve":"If the issue persists after a few attempts, please contact the bot owner.",
+ "internalError":"An internal error occurred while processing this {0}.",
+ "optionMissing":"A required parameter is missing for this command.",
+ "optionInvalid":"One or more parameters provided for this command are invalid.",
+ "optionInvalidChoose":"Please choose between",
+ "unknownCommand":"Please use the help menu for more information.",
+ "noPermissions":"You are not permitted to use this {0}.",
+ "noPermissionsList":"Required permissions (one of the following):",
+ "noPermissionsCooldown":"You cannot use this {0} while on cooldown.",
+ "noPermissionsBlacklist":"You cannot use this {0} because you are blacklisted.",
+ "noPermissionsLimitGlobal":"You cannot create a ticket because the server has reached its maximum ticket limit.",
+ "noPermissionsLimitGlobalUser":"You cannot create a ticket because you have reached your maximum ticket limit.",
+ "noPermissionsLimitOption":"You cannot create a ticket because the server has reached the maximum ticket limit for this option.",
+ "noPermissionsLimitOptionUser":"You cannot create a ticket because you have reached the maximum ticket limit for this option.",
+ "unknownTicket":"Please run this command inside a valid ticket channel.",
+ "deprecatedTicket":"This channel is not recognized as a valid ticket. It may have been created with an older version of the bot.",
+ "notInGuild":"This {0} cannot be used in direct messages. Please use it in a server.",
+ "channelRename":"Due to Discord rate limits, the channel could not be renamed immediately. It will be renamed automatically within 10 minutes if the bot remains online.",
+ "channelRenameSource":"Error source: {0}",
+ "busy":"This {0} is currently unavailable.\nThe ticket is being processed by the bot.\n\nPlease try again in a few seconds.",
+ "closeBeforeMessage":"This ticket cannot be closed or deleted before a user has sent a message.",
+ "closeBeforeAdminMessage":"This ticket cannot be closed or deleted before a support member or admin has sent a message.",
+ "unableToCreateTicket":"You are currently unable to create a ticket."
},
"optionInvalidReasons":{
- "stringRegex":"Value doesn't match pattern!",
- "stringMinLength":"Value needs to be at least {0} characters!",
- "stringMaxLength":"Value needs to be at most {0} characters!",
- "numberInvalid":"Invalid number!",
- "numberMin":"Number needs to be at least {0}!",
- "numberMax":"Number needs to be at most {0}!",
- "numberDecimal":"Number is not allowed to be a decimal!",
- "numberNegative":"Number is not allowed to be negative!",
- "numberPositive":"Number is not allowed to be positive!",
- "numberZero":"Number is not allowed to be zero!",
- "channelNotFound":"Unable to find channel!",
- "userNotFound":"Unable to find user!",
- "roleNotFound":"Unable to find role!",
- "memberNotFound":"Unable to find user!",
- "mentionableNotFound":"Unable to find user or role!",
- "channelType":"Invalid channel type!",
- "notInGuild":"This option requires you to be in a server!"
+ "stringRegex":"The value does not match the required pattern.",
+ "stringMinLength":"The value must be at least {0} characters long.",
+ "stringMaxLength":"The value must be at most {0} characters long.",
+ "numberInvalid":"Invalid number provided.",
+ "numberMin":"The number must be at least {0}.",
+ "numberMax":"The number must be at most {0}.",
+ "numberDecimal":"Decimals are not allowed.",
+ "numberNegative":"Negative numbers are not allowed.",
+ "numberPositive":"Positive numbers are not allowed.",
+ "numberZero":"Zero is not allowed.",
+ "channelNotFound":"Channel not found.",
+ "userNotFound":"User not found.",
+ "roleNotFound":"Role not found.",
+ "memberNotFound":"Member not found.",
+ "mentionableNotFound":"User or role not found.",
+ "channelType":"Invalid channel type.",
+ "notInGuild":"This option can only be used in a server."
},
"permissions":{
- "developer":"You need to be the developer of the bot.",
- "owner":"You need to be the server owner.",
- "admin":"You need to be a server admin.",
- "moderator":"You need to be a moderator.",
- "support":"You need to be in the support team.",
- "member":"You need to be a member.",
- "discord-administrator":"You need to have the `ADMINISTRATOR` permission."
+ "developer":"This action is restricted to the bot developer.",
+ "owner":"You must be the server owner to use this.",
+ "admin":"You must have administrator permissions to use this.",
+ "moderator":"You must be a moderator to use this.",
+ "support":"You must be part of the support team to use this.",
+ "member":"You must be a server member to use this.",
+ "discord-administrator":"You must have the `ADMINISTRATOR` permission."
},
"actionInvalid":{
- "close":"Ticket is already closed!",
- "reopen":"Ticket is not closed yet!",
- "claim":"Ticket is already claimed!",
- "unclaim":"Ticket is not claimed yet!",
- "pin":"Ticket is already pinned!",
- "unpin":"Ticket is not pinned yet!",
- "add":"This user is already able to access the ticket!",
- "remove":"Unable to remove this user from the ticket!"
+ "close":"This ticket is already closed.",
+ "reopen":"This ticket is not closed.",
+ "claim":"This ticket is already claimed.",
+ "unclaim":"This ticket is not claimed.",
+ "pin":"This ticket is already pinned.",
+ "unpin":"This ticket is not pinned.",
+ "add":"This user already has access to this ticket.",
+ "remove":"This user does not have access to this ticket."
}
},
"params":{
@@ -432,107 +432,107 @@
}
},
"commands":{
- "reason":"Specify an optional reason that will be visible in logs.",
- "help":"Get a list of all the available commands.",
- "panel":"Spawn a message with a dropdown or buttons (for ticket creation).",
- "panelId":"The identifier of the panel that you want to spawn.",
- "panelAutoUpdate":"Do you want this panel to automatically update when edited?",
- "ticket":"Instantly create a ticket.",
- "ticketId":"The identifier of the ticket that you want to create.",
- "close":"Close a ticket.",
- "delete":"Delete a ticket.",
- "deleteNoTranscript":"Delete this ticket without creating a transcript.",
- "reopen":"Reopen a ticket.",
- "claim":"Claim a ticket.",
- "claimUser":"Claim this ticket to someone else instead of yourself.",
- "unclaim":"Unclaim a ticket.",
- "pin":"Pin a ticket.",
- "unpin":"Unpin a ticket.",
+ "reason":"Optional reason shown in logs.",
+ "help":"Display all available commands.",
+ "panel":"Create a ticket panel (buttons or dropdown).",
+ "panelId":"ID of the panel to spawn.",
+ "panelAutoUpdate":"Automatically update this panel when edited.",
+ "ticket":"Create a ticket instantly.",
+ "ticketId":"ID of the ticket to create.",
+ "close":"Close this ticket.",
+ "delete":"Delete this ticket.",
+ "deleteNoTranscript":"Delete ticket without saving a transcript.",
+ "reopen":"Reopen a closed ticket.",
+ "claim":"Claim this ticket.",
+ "claimUser":"Claim the ticket for another user.",
+ "unclaim":"Unclaim this ticket.",
+ "pin":"Pin this ticket.",
+ "unpin":"Unpin this ticket.",
- "move":"Move a ticket.",
- "moveId":"The identifier of the option that you want to move to.",
- "rename":"Rename a ticket.",
- "renameName":"The new name for this ticket.",
- "add":"Add a user to a ticket.",
- "addUser":"The user to add.",
- "remove":"Remove a user from a ticket.",
- "removeUser":"The user to remove.",
+ "move":"Move ticket to another option.",
+ "moveId":"Target option ID.",
+ "rename":"Rename this ticket.",
+ "renameName":"New name for the ticket.",
+ "add":"Add a user to this ticket.",
+ "addUser":"User to add.",
+ "remove":"Remove a user from this ticket.",
+ "removeUser":"User to remove.",
- "blacklist":"Manage the ticket blacklist.",
- "blacklistView":"View a list of the current blacklist.",
+ "blacklist":"Manage the blacklist.",
+ "blacklistView":"View all blacklisted users.",
"blacklistAdd":"Add a user to the blacklist.",
"blacklistRemove":"Remove a user from the blacklist.",
- "blacklistGet":"Get the details from a blacklisted user.",
- "blacklistGetUser":"The user to get details from.",
- "stats":"View statistics from the bot, a member or a ticket.",
- "statsReset":"Reset all the stats of the bot (and start counting from zero).",
- "statsGlobal":"View the global stats.",
- "statsUser":"View the stats from a user in the server.",
- "statsUserUser":"The user to view.",
- "statsTicket":"View the stats of a ticket in the server.",
- "statsTicketTicket":"The ticket to view.",
+ "blacklistGet":"View blacklist entry details.",
+ "blacklistGetUser":"User to look up.",
+ "stats":"View bot, user or ticket statistics.",
+ "statsReset":"Reset all bot statistics.",
+ "statsGlobal":"View global bot statistics.",
+ "statsUser":"View a user's statistics.",
+ "statsUserUser":"User to view.",
+ "statsTicket":"View ticket statistics.",
+ "statsTicketTicket":"Ticket to view.",
- "clear":"Delete multiple tickets at the same time.",
- "clearFilter":"The filter for clearing tickets.",
+ "clear":"Delete multiple tickets at once.",
+ "clearFilter":"Filter used when clearing tickets.",
"clearFilters":{
- "all":"All",
- "open":"Open",
- "close":"Closed",
- "claim":"Claimed",
- "unclaim":"Unclaimed",
- "pin":"Pinned",
- "unpin":"Unpinned",
- "autoclose":"Autoclosed"
+ "all":"All tickets",
+ "open":"Open tickets",
+ "close":"Closed tickets",
+ "claim":"Claimed tickets",
+ "unclaim":"Unclaimed tickets",
+ "pin":"Pinned tickets",
+ "unpin":"Unpinned tickets",
+ "autoclose":"Autoclosed tickets"
},
- "autoclose":"Manage autoclose in a ticket.",
- "autocloseDisable":"Disable autoclose in this ticket.",
- "autocloseEnable":"Enable autoclose in this ticket.",
- "autocloseEnableTime":"The amount of hours this ticket needs to be inactive to close it.",
- "autodelete":"Manage autodelete in a ticket.",
- "autodeleteDisable":"Disable autodelete in this ticket.",
- "autodeleteEnable":"Enable autodelete in this ticket.",
- "autodeleteEnableTime":"The amount of days this ticket needs to be inactive to delete it.",
+ "autoclose":"Manage ticket autoclose.",
+ "autocloseDisable":"Disable autoclose.",
+ "autocloseEnable":"Enable autoclose.",
+ "autocloseEnableTime":"Hours of inactivity before closing.",
+ "autodelete":"Manage ticket autodelete.",
+ "autodeleteDisable":"Disable autodelete.",
+ "autodeleteEnable":"Enable autodelete.",
+ "autodeleteEnableTime":"Days of inactivity before deletion.",
- "topic":"Manage the topic of the ticket channel.",
- "topicSet":"Set the topic of the ticket channel.",
- "topicValue":"The new topic of the channel.",
- "topicList":"Get a list of all tickets with their topic and stats.",
- "priority":"Manage the priority of the ticket.",
- "prioritySet":"Set the priority of the ticket.",
- "priorityValue":"The priority of the channel.",
- "priorityGet":"Get the priority of the ticket.",
- "priorityList":"Get a list of all tickets with their priority status.",
- "transfer":"Transfer the ticket ownership from one user to another.",
- "transferUser":"The user to transfer to."
+ "topic":"Manage ticket channel topic.",
+ "topicSet":"Set the ticket channel topic.",
+ "topicValue":"New channel topic text.",
+ "topicList":"List all ticket channel topics.",
+ "priority":"Manage ticket priority.",
+ "prioritySet":"Set ticket priority.",
+ "priorityValue":"Priority level.",
+ "priorityGet":"View ticket priority.",
+ "priorityList":"List all ticket priorities.",
+ "transfer":"Transfer ticket ownership.",
+ "transferUser":"User to transfer to."
},
"helpMenu":{
- "help":"Get a list of all the available commands.",
- "ticket":"Instantly create a ticket.",
- "close":"Close a ticket, this disables writing in this channel.",
- "delete":"Delete a ticket, this creates a transcript when enabled.",
- "reopen":"Reopen a ticket, this enables writing in this channel again.",
- "pin":"Pin a ticket. This will move the ticket to the top and will add a '๐' emoij to the name.",
- "unpin":"Unpin a ticket. The ticket will stay on it's position but will lose the '๐' emoij.",
- "move":"Move a ticket. This will change the type of this ticket.",
- "rename":"Rename a ticket. This will change the channel name of this ticket.",
- "claim":"Claim a ticket. With this, you can let your team know you are handling this ticket.",
- "unclaim":"Unclaim a ticket. With this, you can let your team know that this ticket is free again.",
- "add":"Add a user to a ticket. This will allow the user to read & write in this ticket.",
- "remove":"Remove a user from a ticket. This will remove the ability to read & write for a user in this ticket.",
- "panel":"Spawn a message with a dropdown or buttons (for ticket creation).",
- "blacklistView":"View a list of the current blacklist.",
+ "help":"View all available commands.",
+ "ticket":"Create a ticket instantly.",
+ "close":"Close this ticket and disable messaging in the channel.",
+ "delete":"Delete this ticket (creates a transcript if enabled).",
+ "reopen":"Reopen a closed ticket and restore messaging.",
+ "pin":"Pin this ticket and move it to the top with '๐'.",
+ "unpin":"Unpin this ticket and remove the '๐' emoji.",
+ "move":"Move this ticket to a different option or ticket type.",
+ "rename":"Rename this ticket channel.",
+ "claim":"Claim this ticket to show you are handling it.",
+ "unclaim":"Unclaim this ticket to mark it as available.",
+ "add":"Add a user to this ticket.",
+ "remove":"Remove a user's access from this ticket.",
+ "panel":"Create a ticket panel with buttons or a dropdown.",
+ "blacklistView":"View all blacklisted users.",
"blacklistAdd":"Add a user to the blacklist.",
"blacklistRemove":"Remove a user from the blacklist.",
- "blacklistGet":"Get the details from a blacklisted user.",
- "statsGlobal":"View the global stats.",
- "statsTicket":"View the stats of a ticket in the server.",
- "statsUser":"View the stats from a user in the server.",
- "statsReset":"Reset all the stats of the bot (and start counting from zero).",
- "autocloseDisable":"Disable autoclose in this ticket.",
- "autocloseEnable":"Enable autoclose in this ticket.",
- "autodeleteDisable":"Disable autodelete in this ticket.",
- "autodeleteEnable":"Enable autodelete in this ticket.",
+ "blacklistGet":"View details of a blacklisted user.",
+ "statsGlobal":"View global bot statistics.",
+ "statsTicket":"View statistics for a ticket.",
+ "statsUser":"View statistics for a user.",
+ "statsReset":"Reset all bot statistics.",
+ "autocloseDisable":"Disable autoclose for this ticket.",
+ "autocloseEnable":"Enable autoclose for this ticket.",
+ "autodeleteDisable":"Disable autodelete for this ticket.",
+ "autodeleteEnable":"Enable autodelete for this ticket.",
"categories":{
"general":"General Commands",
"basicTicket":"Basic Ticket Commands",
@@ -545,10 +545,10 @@
},
"stats":{
"scopes":{
- "global":"Global Stats",
- "system":"System Stats",
- "user":"User Stats",
- "ticket":"Ticket Stats",
+ "global":"Global Statistics",
+ "system":"System Statistics",
+ "user":"User Statistics",
+ "ticket":"Ticket Statistics",
"participants":"Participants",
"messages":"Messages"
},
@@ -592,9 +592,9 @@
}
},
"panel":{
- "selectTicket":"Select your ticket",
- "selectRole":"Select your role",
- "selectOption":"Select your option"
+ "selectTicket":"Select a ticket",
+ "selectRole":"Select a role",
+ "selectOption":"Select an option"
},
"priorities":{
"urgent":"Urgent",
diff --git a/languages/estonian.json b/languages/estonian.json
index 241bfec..1225d79 100644
--- a/languages/estonian.json
+++ b/languages/estonian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["iamnotmega","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Estonian",
diff --git a/languages/finnish.json b/languages/finnish.json
index d922108..895a1bf 100644
--- a/languages/finnish.json
+++ b/languages/finnish.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["iamnotmega","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Finnish",
diff --git a/languages/french.json b/languages/french.json
index d50f971..38b582f 100644
--- a/languages/french.json
+++ b/languages/french.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["guillee3"],
"lastedited":"16/02/2026",
"language":"French",
diff --git a/languages/german.json b/languages/german.json
index 5ab33e5..0c8e1c4 100644
--- a/languages/german.json
+++ b/languages/german.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["benzorich"],
"lastedited":"16/02/2026",
"language":"German",
@@ -14,8 +14,8 @@
"typeInfo":"[INFO]",
"headerConfigChecker":"CONFIG CHECKER",
"headerDescription":"Prรผfen Sie auf Fehler in Ihrer Konfigurationsdateien!",
- "footerError":"Der Bot wird nicht starten, bis alle {0}'s repariert sind!",
- "footerWarning":"Es wird empfohlen, vor dem Start alle {0}'s zu korrigieren!",
+ "footerError":"Der Bot wird nicht starten, bis alle {0}en repariert sind!",
+ "footerWarning":"Es wird empfohlen, vor dem Start alle {0}en zu korrigieren!",
"footerSupport":"SUPPORT: {0} - DOCS: {1}",
"compactInformation":"Verwenden Sie {0} fรผr weitere Informationen!",
"dataPath":"Pfad",
diff --git a/languages/greek.json b/languages/greek.json
index 998e304..bc11230 100644
--- a/languages/greek.json
+++ b/languages/greek.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Greek",
diff --git a/languages/hindi.json b/languages/hindi.json
index 30dd621..0addf7e 100644
--- a/languages/hindi.json
+++ b/languages/hindi.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["challenger_nova"],
"lastedited":"16/02/2026",
"language":"Hindi",
diff --git a/languages/hungarian.json b/languages/hungarian.json
index bf989b3..7908d10 100644
--- a/languages/hungarian.json
+++ b/languages/hungarian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["Kornel0706"],
"lastedited":"16/02/2026",
"language":"Hungarian",
diff --git a/languages/indonesian.json b/languages/indonesian.json
index 66c1483..7ea791d 100644
--- a/languages/indonesian.json
+++ b/languages/indonesian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["erxg"],
"lastedited":"16/02/2026",
"language":"Indonesian",
diff --git a/languages/italian.json b/languages/italian.json
index 28a6723..e7be54b 100644
--- a/languages/italian.json
+++ b/languages/italian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["fraden1mvp.","imperatorix_17"],
"lastedited":"16/02/2026",
"language":"Italian",
diff --git a/languages/japanese.json b/languages/japanese.json
index f528a9a..ad91014 100644
--- a/languages/japanese.json
+++ b/languages/japanese.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Japanese",
diff --git a/languages/khmer.json b/languages/khmer.json
index aa347aa..4cd5c55 100644
--- a/languages/khmer.json
+++ b/languages/khmer.json
@@ -1,608 +1,608 @@
{
- "_TRANSLATION": {
- "otversion": "v4.1.3",
- "translators": ["yuuslokrobjakkroval"],
- "lastedited": "19/04/2026",
- "language": "Khmer",
- "automated": false
- },
- "checker": {
- "system": {
- "typeError": "[แแแ แปแ]",
- "headerOpenTicket": "OPEN TICKET",
- "typeWarning": "[แแแแแถแ]",
- "typeInfo": "[แแแแแแถแ]",
- "headerConfigChecker": "CONFIG CHECKER",
- "headerDescription": "แแทแแทแแแแแพแแแแ แปแแแแแปแแฏแแแถแแแแแแแแ
แแถแแแแแแแแ!",
- "footerError": "แแผแแแนแแแทแแ
แถแแแแแแพแแแ แแ แผแแแแ {0} แแถแแแขแแแแแแผแแแถแแแฝแแแปแ!",
- "footerWarning": "แแถแแแแผแแแถแแแแแถแแฑแแแแฝแแแปแ {0} แแถแแแขแแแแปแแแแแ
แถแแแแแแพแ!",
- "footerSupport": "แแแแฝแ: {0} - แฏแแแถแ: {1}",
- "compactInformation": "แแแแพ {0} แแแแแถแแแแแแแแถแแแแแแแ!",
- "dataPath": "แแแแผแ",
- "dataDocs": "แฏแแแถแ",
- "dataMessages": "แแถแ"
+ "_TRANSLATION":{
+ "otversion":"v4.2.0",
+ "translators":["yuuslokrobjakkroval"],
+ "lastedited":"20/05/2026",
+ "language":"Khmer",
+ "automated":false
},
- "messages": {
- "stringTooShort": "แแแแแขแแแแแแแแแทแแขแถแ
แแแแธแแถแ {0} แแฝแขแแแแ!",
- "stringTooLong": "แแแแแขแแแแแแแแแทแแขแถแ
แแแแแถแ {0} แแฝแขแแแแ!",
- "stringLengthInvalid": "แแแแแขแแแแแแแแแแแผแแแแแถแ {0} แแฝแขแแแแ!",
- "stringStartsWith": "แแแแแขแแแแแแแแแแแผแแแแ
แถแแแแแแพแแแแ {0}!",
- "stringEndsWith": "แแแแแขแแแแแแแแแแแผแแแแแแแ
แแแแแ {0}!",
- "stringContains": "แแแแแขแแแแแแแแแแแผแแแแแถแ {0}!",
- "stringChoices": "แแแแแขแแแแแแแแขแถแ
แแถแแแแแแแผแ
แแถแแแแแแแแแปแแแแแ: {0}!",
- "stringRegex": "แแแแแขแแแแแแแแแทแแแแแนแแแแแผแ!",
- "stringInvertedContains": "แแแแแขแแแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแถแ {0}!",
- "stringLowercase": "แแแแแขแแแแแแแแแแแผแแแแแแแแแแถแขแแแแแแผแ
แแแปแแแแแ!",
- "stringUppercase": "แแแแแขแแแแแแแแแแแผแแแแแแแแแแถแขแแแแแแแแแปแแแแแ!",
- "stringSpecialCharacters": "แแแแแขแแแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแถแแแฝแขแแแแแแทแแแ! (a-z, 0-9 แแทแแแแแแแถแแแปแแแแแ)",
- "stringNoSpaces": "แแแแแขแแแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแถแแแแแแแถ!",
- "stringCapitalWord": "แแถแแแแผแแแถแแแแแถแแฑแแแแถแแแแแธแแฝแแแแแแปแแแแแแขแแแแแแแแ
แถแแแแแแพแแแแแขแแแแแแ!",
- "stringCapitalSentence": "แแถแแพแแแ
แแถแแแแแแแแแแแแแแปแแแแแแขแแแแแแแแแทแแ
แถแแแแแแพแแแแแขแแแแแแ!",
- "stringPunctuation": "แแถแแพแแแ
แแถแแแแแแแแแแปแแแแแแขแแแแแแแแแทแแแแแ
แแแแแแแแแแถแแแแแแปแแแแท!",
+ "checker":{
+ "system":{
+ "typeError":"[แแแ แปแ]",
+ "headerOpenTicket":"OPEN TICKET",
+ "typeWarning":"[แแแแแถแ]",
+ "typeInfo":"[แแแแแแถแ]",
+ "headerConfigChecker":"CONFIG CHECKER",
+ "headerDescription":"แแทแแทแแแแแพแแแแ แปแแแแแปแแฏแแแถแแแแแแแแ
แแถแแแแแแแแ!",
+ "footerError":"แแผแแแนแแแทแแ
แถแแแแแแพแแแ แแ แผแแแแ {0} แแถแแแขแแแแแแผแแแถแแแฝแแแปแ!",
+ "footerWarning":"แแถแแแแผแแแถแแแแแถแแฑแแแแฝแแแปแ {0} แแถแแแขแแแแปแแแแแ
แถแแแแแแพแ!",
+ "footerSupport":"แแแแฝแ: {0} - แฏแแแถแ: {1}",
+ "compactInformation":"แแแแพ {0} แแแแแถแแแแแแแแถแแแแแแแ!",
+ "dataPath":"แแแแผแ",
+ "dataDocs":"แฏแแแถแ",
+ "dataMessages":"แแถแ"
+ },
+ "messages":{
+ "stringTooShort":"แแแแแขแแแแแแแแแทแแขแถแ
แแแแธแแถแ {0} แแฝแขแแแแ!",
+ "stringTooLong":"แแแแแขแแแแแแแแแทแแขแถแ
แแแแแถแ {0} แแฝแขแแแแ!",
+ "stringLengthInvalid":"แแแแแขแแแแแแแแแแแผแแแแแถแ {0} แแฝแขแแแแ!",
+ "stringStartsWith":"แแแแแขแแแแแแแแแแแผแแแแ
แถแแแแแแพแแแแ {0}!",
+ "stringEndsWith":"แแแแแขแแแแแแแแแแแผแแแแแแแ
แแแแแ {0}!",
+ "stringContains":"แแแแแขแแแแแแแแแแแผแแแแแถแ {0}!",
+ "stringChoices":"แแแแแขแแแแแแแแขแถแ
แแถแแแแแแแผแ
แแถแแแแแแแแแปแแแแแ: {0}!",
+ "stringRegex":"แแแแแขแแแแแแแแแทแแแแแนแแแแแผแ!",
+ "stringInvertedContains":"แแแแแขแแแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแถแ {0}!",
+ "stringLowercase":"แแแแแขแแแแแแแแแแแผแแแแแแแแแแถแขแแแแแแผแ
แแแปแแแแแ!",
+ "stringUppercase":"แแแแแขแแแแแแแแแแแผแแแแแแแแแแถแขแแแแแแแแแปแแแแแ!",
+ "stringSpecialCharacters":"แแแแแขแแแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแถแแแฝแขแแแแแแทแแแ! (a-z, 0-9 แแทแแแแแแแถแแแปแแแแแ)",
+ "stringNoSpaces":"แแแแแขแแแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแถแแแแแแแถ!",
+ "stringCapitalWord":"แแถแแแแผแแแถแแแแแถแแฑแแแแถแแแแแธแแฝแแแแแแปแแแแแแขแแแแแแแแ
แถแแแแแแพแแแแแขแแแแแแ!",
+ "stringCapitalSentence":"แแถแแพแแแ
แแถแแแแแแแแแแแแแแปแแแแแแขแแแแแแแแแทแแ
แถแแแแแแพแแแแแขแแแแแแ!",
+ "stringPunctuation":"แแถแแพแแแ
แแถแแแแแแแแแแปแแแแแแขแแแแแแแแแทแแแแแ
แแแแแแแแแแถแแแแแแปแแแแท!",
- "numberTooShort": "แแแแแแแแทแแขแถแ
แแแแธแแถแ {0} แแฝแขแแแแ!",
- "numberTooLong": "แแแแแแแแทแแขแถแ
แแแแแถแ {0} แแฝแขแแแแ!",
- "numberLengthInvalid": "แแแแแแแแแแผแแแแแถแ {0} แแฝแขแแแแ!",
- "numberTooSmall": "แแแแแแแแแแผแแแแแแถแแ แแ
แแถแแ {0}!",
- "numberTooLarge": "แแแแแแแแแแผแแแแ
แแแพแแแแแปแ {0}!",
- "numberNotEqual": "แแแแแแแแแแผแแแแแถ {0}!",
- "numberStep": "แแแแแแแแแแผแแแแแถแ
แแแพแแแ {0}!",
- "numberStepOffset": "แแแแแแแแแแผแแแแแถแ
แแแพแแแ {0} แ
แถแแแแแแพแแแธ {1}!",
- "numberStartsWith": "แแแแแแแแแแผแแแแ
แถแแแแแแพแแแแ {0}!",
- "numberEndsWith": "แแแแแแแแแแผแแแแแแแ
แแแแแ {0}!",
- "numberContains": "แแแแแแแแแแผแแแแแถแ {0}!",
- "numberChoices": "แแแแแแแขแถแ
แแถแแแแแแแผแ
แแถแแแแแแแแแปแแแแแ: {0}!",
- "numberFloat": "แแแแแแแแทแแขแถแ
แแถแแแแถแ!",
- "numberNegative": "แแแแแแแแทแแขแถแ
แแถแขแแทแแแแแถแ!",
- "numberPositive": "แแแแแแแแทแแขแถแ
แแถแแทแแแแแถแ!",
- "numberZero": "แแแแแแแแทแแขแถแ
แแถแแผแแแ!",
- "numberNan": "แแแแแแแแทแแขแถแ
แแถ NaN (แแทแแแแแแถแแแ)!",
- "numberInvertedContains": "แแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแถแ {0}!",
+ "numberTooShort":"แแแแแแแแทแแขแถแ
แแแแธแแถแ {0} แแฝแขแแแแ!",
+ "numberTooLong":"แแแแแแแแทแแขแถแ
แแแแแถแ {0} แแฝแขแแแแ!",
+ "numberLengthInvalid":"แแแแแแแแแแผแแแแแถแ {0} แแฝแขแแแแ!",
+ "numberTooSmall":"แแแแแแแแแแผแแแแแแถแแ แแ
แแถแแ {0}!",
+ "numberTooLarge":"แแแแแแแแแแผแแแแ
แแแพแแแแแปแ {0}!",
+ "numberNotEqual":"แแแแแแแแแแผแแแแแถ {0}!",
+ "numberStep":"แแแแแแแแแแผแแแแแถแ
แแแพแแแ {0}!",
+ "numberStepOffset":"แแแแแแแแแแผแแแแแถแ
แแแพแแแ {0} แ
แถแแแแแแพแแแธ {1}!",
+ "numberStartsWith":"แแแแแแแแแแผแแแแ
แถแแแแแแพแแแแ {0}!",
+ "numberEndsWith":"แแแแแแแแแแผแแแแแแแ
แแแแแ {0}!",
+ "numberContains":"แแแแแแแแแแผแแแแแถแ {0}!",
+ "numberChoices":"แแแแแแแขแถแ
แแถแแแแแแแผแ
แแถแแแแแแแแแปแแแแแ: {0}!",
+ "numberFloat":"แแแแแแแแทแแขแถแ
แแถแแแแถแ!",
+ "numberNegative":"แแแแแแแแทแแขแถแ
แแถแขแแทแแแแแถแ!",
+ "numberPositive":"แแแแแแแแทแแขแถแ
แแถแแทแแแแแถแ!",
+ "numberZero":"แแแแแแแแทแแขแถแ
แแถแแผแแแ!",
+ "numberNan":"แแแแแแแแทแแขแถแ
แแถ NaN (แแทแแแแแแถแแแ)!",
+ "numberInvertedContains":"แแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแถแ {0}!",
- "booleanTrue": "Boolean แแแแแทแแขแถแ
แแถ true!",
- "booleanFalse": "Boolean แแแแแทแแขแถแ
แแถ false!",
+ "booleanTrue":"Boolean แแแแแทแแขแถแ
แแถ true!",
+ "booleanFalse":"Boolean แแแแแทแแขแถแ
แแถ false!",
- "arrayEmptyDisabled": "แขแถแแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแแ!",
- "arrayEmptyRequired": "แขแถแแแแแแแแแแผแแแถแแแถแแแถแแฑแแแแแ!",
- "arrayTooShort": "แขแถแแแแแแแแแแผแแแถแแแแแแแแแแถแแ แแ
แแถแแ {0}!",
- "arrayTooLong": "แขแถแแแแแแแแแแผแแแถแแแแแแแแ
แแแพแแแแแปแ {0}!",
- "arrayLengthInvalid": "แขแถแแแแแแแแแแผแแแถแแแแแแแ {0}!",
- "arrayInvalidTypes": "แขแถแแแแแแแขแถแ
แแถแแแแแแแแแผแ
แแถแแแแแแแแแปแแแแแ: {0}!",
- "arrayDouble": "แขแถแแแแแแแแทแแขแแปแแแแถแแฑแแแแแแแแแผแ
แแแแถ!",
+ "arrayEmptyDisabled":"แขแถแแแแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแแ!",
+ "arrayEmptyRequired":"แขแถแแแแแแแแแแผแแแถแแแถแแแถแแฑแแแแแ!",
+ "arrayTooShort":"แขแถแแแแแแแแแแผแแแถแแแแแแแแแแถแแ แแ
แแถแแ {0}!",
+ "arrayTooLong":"แขแถแแแแแแแแแแผแแแถแแแแแแแแ
แแแพแแแแแปแ {0}!",
+ "arrayLengthInvalid":"แขแถแแแแแแแแแแผแแแถแแแแแแแ {0}!",
+ "arrayInvalidTypes":"แขแถแแแแแแแขแถแ
แแถแแแแแแแแแผแ
แแถแแแแแแแแแปแแแแแ: {0}!",
+ "arrayDouble":"แขแถแแแแแแแแทแแขแแปแแแแถแแฑแแแแแแแแแผแ
แแแแถ!",
- "discordInvalidId": "แแแแแถ discord {0} id แแทแแแแแนแแแแแผแ!",
- "discordInvalidIdOptions": "แแแแแถ discord {0} id แแทแแแแแนแแแแแผแ! แขแแแแแแขแถแ
แแแแพ: {1}!",
- "discordInvalidToken": "แแแแแถ discord token แแทแแแแแนแแแแแผแ (แแแแปแแแแแแแ)!",
- "colorInvalid": "แแแแแถแแแ hex แแทแแแแแนแแแแแผแ!",
- "emojiTooShort": "แแแแแขแแแแแแแแแแแผแแแถแ emoji แแแถแแ แแ
แแถแแ {0}!",
- "emojiTooLong": "แแแแแขแแแแแแแแแแแผแแแถแ emoji แ
แแแพแแแแแปแ {0}!",
- "emojiCustom": "Emoji แแแแแทแแขแถแ
แแถ custom discord emoji!",
- "emojiInvalid": "แแแแแถ emoji แแทแแแแแนแแแแแผแ!",
- "urlInvalid": "URL แแแแแทแแแแแนแแแแแผแ!",
- "urlInvalidHttp": "URL แแแแขแถแ
แแแแพแแ https:// protocol แแแปแแแแแ!",
- "urlInvalidProtocol": "URL แแแแขแถแ
แแแแพแแ http:// แแทแ https:// protocols แแแปแแแแแ!",
- "urlInvalidHostname": "URL แแแแแถแ hostname แแทแแแแแผแแแถแแขแแปแแแแถแ!",
- "urlInvalidExtension": "URL แแแแแถแแแแแแแแแแแแแแทแแแแแนแแแแแผแ! แแแแพแแแพแ: {0}!",
- "urlInvalidPath": "URL แแแแแถแแแแแผแแแทแแแแแนแแแแแผแ!",
- "idNotUnique": "id แแแแแทแแแแแฝแ, แแแแพ id แแแแแแแแ!",
- "idNonExistent": "id {0} แแทแแแถแ!",
+ "discordInvalidId":"แแแแแถ discord {0} id แแทแแแแแนแแแแแผแ!",
+ "discordInvalidIdOptions":"แแแแแถ discord {0} id แแทแแแแแนแแแแแผแ! แขแแแแแแขแถแ
แแแแพ: {1}!",
+ "discordInvalidToken":"แแแแแถ discord token แแทแแแแแนแแแแแผแ (แแแแปแแแแแแแ)!",
+ "colorInvalid":"แแแแแถแแแ hex แแทแแแแแนแแแแแผแ!",
+ "emojiTooShort":"แแแแแขแแแแแแแแแแแผแแแถแ emoji แแแถแแ แแ
แแถแแ {0}!",
+ "emojiTooLong":"แแแแแขแแแแแแแแแแแผแแแถแ emoji แ
แแแพแแแแแปแ {0}!",
+ "emojiCustom":"Emoji แแแแแทแแขแถแ
แแถ custom discord emoji!",
+ "emojiInvalid":"แแแแแถ emoji แแทแแแแแนแแแแแผแ!",
+ "urlInvalid":"URL แแแแแทแแแแแนแแแแแผแ!",
+ "urlInvalidHttp":"URL แแแแขแถแ
แแแแพแแ https:// protocol แแแปแแแแแ!",
+ "urlInvalidProtocol":"URL แแแแขแถแ
แแแแพแแ http:// แแทแ https:// protocols แแแปแแแแแ!",
+ "urlInvalidHostname":"URL แแแแแถแ hostname แแทแแแแแผแแแถแแขแแปแแแแถแ!",
+ "urlInvalidExtension":"URL แแแแแถแแแแแแแแแแแแแแทแแแแแนแแแแแผแ! แแแแพแแแพแ: {0}!",
+ "urlInvalidPath":"URL แแแแแถแแแแแผแแแทแแแแแนแแแแแผแ!",
+ "idNotUnique":"id แแแแแทแแแแแฝแ, แแแแพ id แแแแแแแแ!",
+ "idNonExistent":"id {0} แแทแแแถแ!",
- "invalidType": "แแแแแแแแแแแแแแทแแแแแแแผแแแถแแแแแแ: {0}!",
- "propertyMissing": "แแแแแแแแแแแแแแท {0} แแถแแแแธแแแแแปแแแ!",
- "propertyOptional": "แแแแแแแแแแแแแแท {0} แแถแแแแแพแแแแแแถแแแแแแแปแแแ!",
- "objectDisabled": "แแแแแปแแแแแแแผแแแถแแแทแ, แแพแแแถแแแแแแแพ {0}!",
- "nullInvalid": "แแแแแแแแแแแแแแทแแแแแทแแขแถแ
แแถ null!",
- "switchInvalidType": "แแแแแแแผแแแถแแแแแแแแผแ
แแถแแแแแแ: {0}!",
- "objectSwitchInvalid": "แแแแแปแแแแแแแผแแแถแแแแแแแแผแ
แแถแแแแแแ: {0}!",
+ "invalidType":"แแแแแแแแแแแแแแทแแแแแแแผแแแถแแแแแแ: {0}!",
+ "propertyMissing":"แแแแแแแแแแแแแแท {0} แแถแแแแธแแแแแปแแแ!",
+ "propertyOptional":"แแแแแแแแแแแแแแท {0} แแถแแแแแพแแแแแแถแแแแแแแปแแแ!",
+ "objectDisabled":"แแแแแปแแแแแแแผแแแถแแแทแ, แแพแแแถแแแแแแแพ {0}!",
+ "nullInvalid":"แแแแแแแแแแแแแแทแแแแแทแแขแถแ
แแถ null!",
+ "switchInvalidType":"แแแแแแแผแแแถแแแแแแแแผแ
แแถแแแแแแ: {0}!",
+ "objectSwitchInvalid":"แแแแแปแแแแแแแผแแแถแแแแแแแแผแ
แแถแแแแแแ: {0}!",
- "invalidLanguage": "แแแแแถแแถแแถแแทแแแแแนแแแแแผแ!",
- "invalidButton": "แแแผแแปแแแแแแแแผแแแถแ {0} แฌ {1} แแแถแแแทแ
แแถแแ!",
- "unusedOption": "แแแแแพแ {0} แแทแแแแแผแแแถแแแแแพ!",
- "unusedQuestion": "แแแแฝแ {0} แแทแแแแแผแแแถแแแแแพ!",
- "dropdownOption": "Panel แแแแแถแ dropdown แแพแแขแถแ
แแถแแแแแแแแพแแแแแแแ 'ticket' แแแปแแแแแ!",
- "customInvalidVersion": "แแแแแแแแแถแแแแแแถแแแแแแปแ config แแแแแขแแแแแทแแแแแผแแแแแถ! แแผแแแแแถแแแแถแขแแแแแถแแแแแพแแ
แแ
แปแแแแแแแแถแ config แแ
แแแแแแแแธแแแแปแ!"
+ "invalidLanguage":"แแแแแถแแถแแถแแทแแแแแนแแแแแผแ!",
+ "invalidButton":"แแแผแแปแแแแแแแแผแแแถแ {0} แฌ {1} แแแถแแแทแ
แแถแแ!",
+ "unusedOption":"แแแแแพแ {0} แแทแแแแแผแแแถแแแแแพ!",
+ "unusedQuestion":"แแแแฝแ {0} แแทแแแแแผแแแถแแแแแพ!",
+ "dropdownOption":"Panel แแแแแถแ dropdown แแพแแขแถแ
แแถแแแแแแแแพแแแแแแแ 'ticket' แแแปแแแแแ!",
+ "customInvalidVersion":"แแแแแแแแแถแแแแแแถแแแแแแปแ config แแแแแขแแแแแทแแแแแผแแแแแถ! แแผแแแแแถแแแแถแขแแแแแถแแแแแพแแ
แแ
แปแแแแแแแแถแ config แแ
แแแแแแแแธแแแแปแ!"
+ }
+ },
+ "actions":{
+ "buttons":{
+ "create":"แ
แผแแแพแแแแแปแแแ",
+ "close":"แแทแแแแแปแแแ",
+ "delete":"แแปแแแแแปแแแ",
+ "reopen":"แแพแแแแแปแแแแกแพแแแทแ",
+ "claim":"แแแฝแแแแแปแแแ",
+ "unclaim":"แแแแแแฝแแแแแปแแแ",
+ "pin":"แแถแแแแแแปแแแแแปแแแ",
+ "unpin":"แแแแแแปแแแแแปแแแ",
+ "clear":"แแปแแแแแปแแแแแถแแแขแแ",
+ "helpSwitchSlash":"แแพแแแถแแแแแแแแถ Slash",
+ "helpSwitchText":"แแพแแแถแแแแแแแแถแขแแแแ",
+ "helpPage":"แแแแแ {0}",
+ "withReason":"แแถแแฝแแ แแแปแแ",
+ "withoutTranscript":"แแแแถแ Transcript"
+ },
+ "titles":{
+ "created":"แแถแแแแแแพแแแแแปแแแ",
+ "close":"แแถแแแทแแแแแปแแแ",
+ "delete":"แแถแแแปแแแแแปแแแ",
+ "reopen":"แแถแแแพแแแแแปแแแแกแพแแแทแ",
+ "claim":"แแถแแแแฝแแแแแปแแแ",
+ "unclaim":"แแถแแแแแแแฝแแแแแปแแแ",
+ "pin":"แแถแแแถแแแแแแปแแแแแปแแแ",
+ "unpin":"แแถแแแแแแแปแแแแแปแแแ",
+ "rename":"แแถแแแแแผแแแแแแแแแแปแแแ",
+ "move":"แแถแแแแแถแแแแแแผแแแแแปแแแ",
+ "add":"แแถแแแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแปแแแ",
+ "remove":"แแถแแแแขแแแแแแแพแแแแถแแแแธแแแแปแแแ",
+
+ "help":"แแถแแแแแแแแถแแแแแถแ",
+ "statsReset":"แแแแแแแแแทแแทแกแพแแแทแ",
+ "blacklistAdd":"แขแแแแแแแพแแแแถแแแแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
",
+ "blacklistRemove":"แขแแแแแแแพแแแแถแแแแแแผแแแถแแแแแแแ",
+ "blacklistGet":"แขแแแแแแแพแแแแถแแแแแแปแแแแแแธแแแแ
",
+ "blacklistView":"แแแแแธแแแแ
แแ
แแ
แปแแแแแแ",
+ "blacklistAddDm":"แแแแผแแแถแแแแแแแแแ
แแแแแธแแแแ
",
+ "blacklistRemoveDm":"แแแแผแแแถแแแแ
แแแแธแแแแแธแแแแ
",
+ "clear":"แแถแแแแแขแถแแแแแปแแแ",
+ "clearTickets":"แแแแขแถแแแแแปแแแ",
+ "roles":"แแฝแแถแแธแแถแแแแแพแแ
แแ
แปแแแแแแแแถแ",
+
+ "autoclose":"แแแแปแแแแแถแแแทแแแแแแแแแแแแแแแแแท",
+ "autocloseEnabled":"แแถแแแพแ Autoclose",
+ "autocloseDisabled":"แแถแแแทแ Autoclose",
+ "autodelete":"แแแแปแแแแแถแแแปแแแแแแแแแแแแแแแแแท",
+ "autodeleteEnabled":"แแถแแแพแ Autodelete",
+ "autodeleteDisabled":"แแถแแแทแ Autodelete",
+
+ "topicSet":"แแถแแแแแผแแแแแแถแแแ",
+ "prioritySet":"แแถแแแแแผแแขแถแแทแแถแ",
+ "priorityGet":"แขแถแแทแแถแแแแแปแแแ",
+ "transfer":"แแถแแแแแแแแแแปแแแ"
+ },
+ "descriptions":{
+ "create":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแแพแแ แ
แปแ
แแแผแแปแแแถแแแแแแแแพแแแแธแ
แผแแแแแพ!",
+ "close":"แแแแปแแแแแแแผแแแถแแแทแแแแแแแแแแ!",
+ "delete":"แแแแปแแแแแแแผแแแถแแแปแแแแแแแแแแ!",
+ "reopen":"แแแแปแแแแแแแผแแแถแแแพแแกแพแแแทแแแแแแแแแแ!",
+ "claim":"แแแแปแแแแแแแผแแแถแแแแฝแแแแแแแแแแ!",
+ "unclaim":"แแแแปแแแแแแแผแแแถแแแแแแแฝแแแแแแแแแแ!",
+ "pin":"แแแแปแแแแแแแผแแแถแแแถแแแแแแปแแแแแแแแแแ!",
+ "unpin":"แแแแปแแแแแแแผแแแถแแแแแแแปแแแแแแแแแแ!",
+ "rename":"แแแแปแแแแแแแผแแแถแแแแแผแแแแแแแแ
{0} แแแแแแแแแ!",
+ "move":"แแแแปแแแแแแแผแแแถแแแแแถแแแแแแผแแแ
{0} แแแแแแแแแ!",
+ "add":"{0} แแแแผแแแถแแแแแแแแแ
แแแแปแแแแแแแแแแแแ!",
+ "remove":"{0} แแแแผแแแถแแแแ
แแแแธแแแแปแแแแแแแแแแแแ!",
+
+ "helpExplanation":"`` => แแแถแแแถแแแแแแแ
แถแแแถแ
แ\n`[name]` => แแแถแแแถแแแแแแแแแแแ
แ
แทแแแ",
+ "statsReset":"แแแแทแแทแแผแแแแแผแแแถแแแแแแแกแพแแแทแแแแแแแแแแ!",
+ "statsError":"แแทแแขแถแ
แแพแแแแแทแแทแแแแปแแแ!\n{0} แแทแแแแแแถแแแแปแแแ!",
+ "blacklistAdd":"{0} แแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
แแแแแแแแแ!",
+ "blacklistRemove":"{0} แแแแผแแแถแแแแแแแแแแแแแแแแ!",
+ "blacklistGetSuccess":"{0} แแแแทแแแแแปแแแแแแธแแแแ
แแ
แแ
แปแแแแแแ!",
+ "blacklistGetEmpty":"{0} แแทแแแแแทแแแแแปแแแแแแธแแแแ
แแ
แแ
แปแแแแแแ!",
+ "blacklistViewEmpty":"แแทแแแถแแแแถแแขแแแแแถแแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
!",
+ "blacklistViewTip":"แแแแพ \"/blacklist add\" แแพแแแแธแแถแแแขแแแแแแแพแแแแปแแแแแแธแแแแ
!",
+ "clearVerify":"แแพแขแแแแแแแถแแแแถแ
แแแแปแแแแแปแแแแ
แแแพแ?\nแแแแแแแถแแแแแแทแแขแถแ
แแแแกแแแแแแทแ!",
+ "clearReady":"แแแแปแแแ {0} แแแแผแแแถแแแปแแแแแแแแแแ!",
+ "rolesEmpty":"แแทแแแถแแแฝแแถแแธแแถแแแแผแแแถแแแแแพแแ
แแ
แปแแแแแแแแถแ!",
+
+ "autocloseLeave":"แแแแปแแแแแแแแแแผแแแถแแแทแแแแแแแแแแแแแแแแแท แแแแแถแแขแแแแแแแแพแแแถแแ
แถแแ
แแแแธแแแถแแแธแแแแแแพ!",
+ "autocloseTimeout":"แแแแปแแแแแแแแแแผแแแถแแแทแแแแแแแแแแแแแแแแแท แแแแแถแแแถแแทแแแแแแแแพแแแธ `{0}h`!",
+ "autodeleteLeave":"แแแแปแแแแแแแแแแผแแแถแแแปแแแแแแแแแแแแแแแแแท แแแแแถแแขแแแแแแแแพแแแถแแ
แถแแ
แแแแธแแแถแแแธแแแแแแพ!",
+ "autodeleteTimeout":"แแแแปแแแแแแแแแแผแแแถแแแปแแแแแแแแแแแแแแแแแท แแแแแถแแแถแแทแแแแแแแแพแแแธ `{0} แแแแ`!",
+ "autocloseEnabled":"Autoclose แแแแผแแแถแแแพแแแแแปแแแแแปแแแแแแ!\nแแถแแนแแแแแผแแแถแแแทแแแ
แแแแแทแแแแแแแแพแแแธ `{0}h`!",
+ "autocloseDisabled":"Autoclose แแแแผแแแถแแแทแแแแแปแแแแแปแแแแแแ!\nแแถแแนแแแทแแแแแผแแแถแแแทแแแแแแแแแแแแแแแแแทแแแแแ!",
+ "autodeleteEnabled":"Autodelete แแแแผแแแถแแแพแแแแแปแแแแแปแแแแแแ!\nแแถแแนแแแแแผแแแถแแแปแแแ
แแแแแทแแแแแแแแพแแแธ `{0} แแแแ`!",
+ "autodeleteDisabled":"Autodelete แแแแผแแแถแแแทแแแแแปแแแแแปแแแแแแ!\nแแถแแนแแแทแแแแแผแแแถแแแปแแแแแแแแแแแแแแแแแทแแแแแ!",
+
+ "ticketMessageLimit":"แขแแแแขแถแ
แแแแแพแแแแแปแแแ {0} แแแแปแแแแแแแแฝแ!",
+ "ticketMessageAutoclose":"แแแแปแแแแแแแแนแแแแแผแแแถแแแทแแแแแแแแแแแแแแแแแท แแ
แแแแแทแแแแแแ {0}h!",
+ "ticketMessageAutodelete":"แแแแปแแแแแแแแนแแแแแผแแแถแแแปแแแแแแแแแแแแแแแแแท แแ
แแแแแทแแแแแแ {0} แแแแ!",
+ "panelReady":"Panel แแถแแแ
แแแแปแแแถแแแแแ!\nแแถแแแแแขแถแ
แแปแแแถแแ แพแ!",
+
+ "topicSet":"แแแแแถแแแแแแแแถแแแแแผแแแถแแแแแผแแแแ {0} แแแแแแแแแ!",
+ "prioritySet":"แขแถแแทแแถแแแแแปแแแแแแแผแแแถแแแแแผแแแ
{0} แแแ {1} แแแแแแแแแ!",
+ "priorityGet":"แขแถแแทแแถแแแ
แแ
แปแแแแแแแแแแแแแแปแแแแแแแแบ {0}แ",
+ "transfer":"แแถแแแถแแแ
แถแแแแแแปแแแแแแแผแแแถแแแแแแแแธ {0} แแ
{1} แแแ {2} แแแแแแแแแ!"
+ },
+ "modal":{
+ "closePlaceholder":"แ แแแปแขแแแธแขแแแแแทแแแแแปแแแแแแ?",
+ "deletePlaceholder":"แ แแแปแขแแแธแขแแแแแปแแแแแปแแแแแแ?",
+ "reopenPlaceholder":"แ แแแปแขแแแธแขแแแแแพแแแแแปแแแแแแแกแพแแแทแ?",
+ "claimPlaceholder":"แ แแแปแขแแแธแขแแแแแแฝแแแแแปแแแแแแ?",
+ "unclaimPlaceholder":"แ แแแปแขแแแธแขแแแแแแแแแฝแแแแแปแแแแแแ?",
+ "pinPlaceholder":"แ แแแปแขแแแธแขแแแแแถแแแแแแปแแแแแปแแแแแแ?",
+ "unpinPlaceholder":"แ แแแปแขแแแธแขแแแแแแแแแปแแแแแปแแแแแแ?"
+ },
+ "logs":{
+ "createLog":"แแแแปแแแแแแแธแแแแผแแแถแแแแแแพแแแแ {0}!",
+ "closeLog":"แแแแปแแแแแแแแแแผแแแถแแแทแแแแ {0}!",
+ "closeDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแทแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "deleteLog":"แแแแปแแแแแแแแแแผแแแถแแแปแแแแ {0}!",
+ "deleteDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแปแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "reopenLog":"แแแแปแแแแแแแแแแผแแแถแแแพแแกแพแแแทแแแแ {0}!",
+ "reopenDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแพแแกแพแแแทแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "claimLog":"แแแแปแแแแแแแแแแผแแแถแแแแฝแแแแ {0}!",
+ "claimDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแฝแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "unclaimLog":"แแแแปแแแแแแแแแแผแแแถแแแแแแแฝแแแแ {0}!",
+ "unclaimDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแแแฝแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "pinLog":"แแแแปแแแแแแแแแแผแแแถแแแถแแแแแแปแแแแ {0}!",
+ "pinDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแถแแแแแแปแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "unpinLog":"แแแแปแแแแแแแแแแผแแแถแแแแแแแปแแแแ {0}!",
+ "unpinDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแแแปแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "renameLog":"แแแแปแแแแแแแแแแผแแแถแแแแแผแแแแแแแแ
{0} แแแ {1}!",
+ "renameDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแผแแแแแแแแ
{0} แแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "moveLog":"แแแแปแแแแแแแแแแผแแแถแแแแแถแแแแแแผแแแ
{0} แแแ {1}!",
+ "moveDm":"แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแถแแแแแแผแแแ
{0} แแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "addLog":"{0} แแแแผแแแถแแแแแแแแแ
แแแแปแแแแแแแแแ {1}!",
+ "addDm":"{0} แแแแผแแแถแแแแแแแแแ
แแแแปแแแแแแแแขแแแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "removeLog":"{0} แแแแผแแแถแแแแ
แแแแธแแแแปแแแแแแแแแ {1}!",
+ "removeDm":"{0} แแแแผแแแถแแแแ
แแแแธแแแแปแแแแแแแแขแแแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+
+ "blacklistAddLog":"{0} แแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
แแแ {1}!",
+ "blacklistRemoveLog":"{0} แแแแผแแแถแแแแ
แแแแธแแแแแธแแแแ
แแแ {1}!",
+ "blacklistAddDm":"แขแแแแแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!\nแ
แถแแแแธแแแแแแ แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ!",
+ "blacklistRemoveDm":"แขแแแแแแแผแแแถแแแแ
แแแแธแแแแแธแแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!\nแฅแกแผแแขแแแแขแถแ
แแแแแพแแแแแปแแแแแถแแแแแแแแ!",
+ "clearLog":"แแแแปแแแ {0} แแแแผแแแถแแแปแแแแ {1}!",
+
+ "transferLog":"แแถแแแถแแแ
แถแแแแแแปแแแแแแแแแแผแแแถแแแแแแแแธ {0} แแ
{1} แแแ {2}!",
+ "transferDm":"แแถแแแถแแแ
แถแแแแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแแแแธ {0} แแ
{1} แแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "prioritySetLog":"แขแถแแทแแถแแแแแปแแแแแแแแแแผแแแถแแแแแผแแแ
{0} แแแ {1}!",
+ "prioritySetDm":"แขแถแแทแแถแแแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแผแแแ
{0} แแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
+ "roleUpdateLog":"{0} แแถแแแแแพแแ
แแ
แปแแแแแแแแถแแแฝแแถแแธแแแแแแแแฝแ!",
+ "roleUpdateDm":"แแฝแแถแแธแแแแแขแแแแแแแปแแแแถแแแธแแแแแแพแแแแแแพแแแแแผแแแถแแแแแพแแ
แแ
แปแแแแแแแแถแ!"
+ }
+ },
+ "transcripts":{
+ "success":{
+ "visit":"แ
แผแแแพแ Transcript",
+ "ready":"Transcript แแแแผแแแถแแแแแแพแ",
+ "textFileDescription":"แแแแแถ transcript แขแแแแแแแแแแแแปแแแแแแแแถแแแปแ!",
+ "htmlProgress":"แแผแแแแแ
แถแ แแแ html transcript แแแแปแแแแแผแแแถแแแแแพแแแถแ...",
+
+ "createdChannel":"transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแปแแแแถแแแธแแแแแแพ!",
+ "createdCreator":"transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแแถแแแแแแปแแแแแแแแขแแแ!",
+ "createdParticipant":"transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแปแแแแแปแแแแแแแขแแแแแถแแ
แผแแแฝแ!",
+ "createdActiveAdmin":"transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแปแแแแแปแแแแแแแขแแแแแถแแ
แผแแแฝแแแถแขแแแแแแแแแแแแ!",
+ "createdEveryAdmin":"transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแปแแแแแปแแแแแแแขแแแแแถแขแแแแแแแแแแแแ!",
+ "createdOther":"transcript {0} แแแแธแแแแผแแแถแแแแแแพแ!"
+ },
+ "errors":{
+ "retry":"แแแแถแแถแแแแแแแแ",
+ "continue":"แแปแแแแแแแแถแ Transcript",
+ "backup":"แแแแแพแ Transcript แแแแแปแ",
+ "error":"แแถแแแแแ แถแแแแแแแแปแแแถแแแแแแพแ transcriptแ\nแขแแแแ
แแแแแแพแขแแแธ?\n\nแแแแปแแแแแแแแนแแแทแแแแแผแแแถแแแปแแแ แแ แผแแขแแแแ
แปแ
แแแผแแปแแแถแแฝแแ",
+ "title":"แแแ แปแ Transcript"
+ },
+ "text":{
+ "messagesTitle":"แแถแ",
+ "embedTitle":"EMBED",
+ "fileTitle":"แฏแแแถแ",
+ "fieldsTitle":"แแถแ",
+ "reactionsTitle":"แแแแแทแแแแ",
+ "statsTitle":"แแแแทแแท",
+ "emptyContent":"<แแถแแทแแถแแแ>",
+ "noTitle":"<แแแแถแแ
แแแแแพแ>",
+ "noDesc":"<แแแแถแแแถแแแทแแแแแถ>"
+ }
+ },
+ "errors":{
+ "titles":{
+ "internalError":"แแแ แปแแแแแแแแแปแ",
+ "optionMissing":"แแแแแพแแแถแแแแแแแแถแแถแแ",
+ "optionInvalid":"แแแแแพแแแถแแแแแแแแถแแทแแแแแนแแแแแผแ",
+ "unknownCommand":"แแถแแแแแแแแถแแทแแแแแถแแ",
+ "noPermissions":"แแแแถแแแทแแแแท",
+ "unknownTicket":"แแแแปแแแแแทแแแแแถแแ",
+ "deprecatedTicket":"แแแแปแแแแ แฝแแแแแ",
+ "unknownOption":"แแแแแพแแแทแแแแแถแแ",
+ "unknownPanel":"Panel แแทแแแแแถแแ",
+ "notInGuild":"แแทแแแ
แแแแปแแแแถแแแธแแแแแแพ",
+ "channelRename":"แแทแแขแถแ
แแแแผแแแแแแแแแแแถแ",
+ "busy":"แแแแปแแแแแแแปแแแแแพแแแถแ",
+ "permissionError":"แแแ แปแแแทแแแแท"
+ },
+ "descriptions":{
+ "askForInfo":"แแแแถแแแแแแแแแ
แถแแแแผแแแแแแแแแถแแแแแแแแถแแแแแแแ!",
+ "askForInfoResolve":"แแแแถแแแแแแแแแ
แถแแแแผแแแแ แแแแแทแแแพแแแแ แถแแแแแทแแแแแแแแถแแแแแแถแแแแธแแแแถแแถแแแฝแแ
แแแฝแแ",
+ "internalError":"แแแถแแแแแแแปแแแถแแแแแพแแแ {0} แแแแแถแแแแ แปแแแแแแแแแปแ!",
+ "optionMissing":"แแแถแแแถแแแแแแแ
แถแแแถแ
แแแแแแแแแปแแแถแแแแแแแแถแแแ!",
+ "optionInvalid":"แแแถแแแถแแแแแแแแแแปแแแถแแแแแแแแถแแแแแทแแแแแนแแแแแผแ!",
+ "optionInvalidChoose":"แแแแพแแแพแแแแถแ",
+ "unknownCommand":"แแผแแ
แผแแแพแแแแบแแปแแแแแฝแแแแแแถแแแแแแแแถแแแแแแแ!",
+ "noPermissions":"แขแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแแแพ {0} แแแ!",
+ "noPermissionsList":"แแทแแแแทแแแแแแแผแแแถแ: (แแฝแแแแแปแแ
แแแแ)",
+ "noPermissionsCooldown":"แขแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแแแพ {0} แแแ แแแแแถแแขแแแแแถแแแแแแแแแแแแถแแ!",
+ "noPermissionsBlacklist":"แขแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแแแพ {0} แแแ แแแแแถแแขแแแแแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
!",
+ "noPermissionsLimitGlobal":"แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ แแแแแถแแแแถแแแธแแแแแแพแแถแแแแแแแแแแแแแแแแปแแแแ
แแแพแแแแแปแ!",
+ "noPermissionsLimitGlobalUser":"แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ แแแแแถแแขแแแแแถแแแแแแแแแแแแแแแแปแแแแ
แแแพแแแแแปแ!",
+ "noPermissionsLimitOption":"แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ แแแแแถแแแแถแแแธแแแแแแพแแถแแแแแแแแแแแแแแแแปแแแแ
แแแพแแแแแปแแแแแแถแแแแแแแพแแแแ!",
+ "noPermissionsLimitOptionUser":"แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ แแแแแถแแขแแแแแถแแแแแแแแแแแแแแแแปแแแแ
แแแพแแแแแปแแแแแแถแแแแแแแพแแแแ!",
+ "unknownTicket":"แแผแแแถแแแแแแแถแแแแแแแแถแแแแแแแแแแแแแแปแแแแแปแแแแแแแนแแแแแผแ!",
+ "deprecatedTicket":"แแแแแถแแแ
แแ
แปแแแแแแแแทแแแแแแถแแแแปแแแแแแแนแแแแแผแ! แแถแแแแ แแแแถแแแแปแแแแแธ Open Ticket แแแแแ
แถแแ!",
+ "notInGuild":"{0} แแแแแทแแแแแพแแแถแแแแแปแ DM! แแผแแแถแแแแแแแแแแแแแแแแปแแแแถแแแธแแแแแแพ!",
+ "channelRename":"แแแแแถแ discord ratelimits, แแถแแทแแขแถแ
แแ
แแถแแแแแแถแแแแผแแแแแปแแแถแแแแแผแแแแแแแแแแแถแแ แแแแแถแแแนแแแแแผแแแถแแแแแผแแแแแแแแแแแแแแแแแแแแแแท แแแแปแแแแแแแ 10 แแถแแธ แแแแแทแแแพแแผแแแทแแแถแแ
แถแแแแแแพแแกแพแแแทแแ",
+ "channelRenameSource":"แแแแแแแแ แปแแแแแแบ: {0}",
+ "busy":"แแทแแขแถแ
แแแแพ {0} แแแ!\nแแแแปแแแแแแแปแแแแแผแแแถแแแแแพแแแถแแแแแแผแแ\n\nแแผแแแแแถแแถแแแแแแแแแแแแปแแแธแแแธแแทแแถแแธ!",
+ "closeBeforeMessage":"แแแแปแแแแแแแแทแแขแถแ
แแทแ/แแปแแแปแแแถแแแถแแแธแขแแแแแแแพแ",
+ "closeBeforeAdminMessage":"แแแแปแแแแแแแแทแแขแถแ
แแทแ/แแปแแแปแแแถแแแถแแแธแขแแแแแแแแแแแแแแแแปแแแ แฌแแแถแแทแแแแแฝแแ",
+ "unableToCreateTicket":"แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแแ"
+ },
+ "optionInvalidReasons":{
+ "stringRegex":"แแแแแแแทแแแแแผแแแนแแแแแถแ!",
+ "stringMinLength":"แแแแแแแแแผแแแถแแแแถแแ แแ
แแถแแ {0} แแฝแขแแแแ!",
+ "stringMaxLength":"แแแแแแแแแผแแแถแแ
แแแพแแแแแปแ {0} แแฝแขแแแแ!",
+ "numberInvalid":"แแแแแทแแแแแนแแแแแผแ!",
+ "numberMin":"แแแแแแแผแแแถแแแแถแแ แแ
แแถแแ {0}!",
+ "numberMax":"แแแแแแแผแแแถแแ
แแแพแแแแแปแ {0}!",
+ "numberDecimal":"แแแแแทแแแแแผแแแถแแขแแปแแแแถแแแถแแแแถแ!",
+ "numberNegative":"แแแแแทแแแแแผแแแถแแขแแปแแแแถแแแถแขแแทแแแแแถแ!",
+ "numberPositive":"แแแแแทแแแแแผแแแถแแขแแปแแแแถแแแถแแทแแแแแถแ!",
+ "numberZero":"แแแแแทแแแแแผแแแถแแขแแปแแแแถแแแถแแผแแแ!",
+ "channelNotFound":"แแแแแแแถแแแทแแแพแ!",
+ "userNotFound":"แแแขแแแแแแแพแแแแถแแแแทแแแพแ!",
+ "roleNotFound":"แแแแฝแแถแแธแแทแแแพแ!",
+ "memberNotFound":"แแแขแแแแแแแพแแแแถแแแแทแแแพแ!",
+ "mentionableNotFound":"แแแขแแแแแแแพแแแแถแแ แฌแแฝแแถแแธแแทแแแพแ!",
+ "channelType":"แแแแแแแแแแแถแแแทแแแแแนแแแแแผแ!",
+ "notInGuild":"แแแแแพแแแแแแถแแแถแแฑแแแขแแแแแ
แแแแปแแแแถแแแธแแแแแแพ!"
+ },
+ "permissions":{
+ "developer":"แขแแแแแแแผแแแถ developer แแแแแแผแแ",
+ "owner":"แขแแแแแแแผแแแถแแแ
แถแแแแแถแแแธแแแแแแพแ",
+ "admin":"แขแแแแแแแผแแแถ admin แแแถแแแธแแแแแแพแ",
+ "moderator":"แขแแแแแแแผแแแถแขแแแแแแแแปแแแแแแฝแแ",
+ "support":"แขแแแแแแแผแแแ
แแแแปแแแแแปแแแแแฝแแ",
+ "member":"แขแแแแแแแผแแแถแแแถแแทแแ",
+ "discord-administrator":"แขแแแแแแแผแแแถแแแทแแแแท `ADMINISTRATOR`แ"
+ },
+ "actionInvalid":{
+ "close":"แแแแปแแแแแถแแแทแแ แพแ!",
+ "reopen":"แแแแปแแแแแทแแแถแแแแทแ!",
+ "claim":"แแแแปแแแแแถแแแแฝแแ แพแ!",
+ "unclaim":"แแแแปแแแแแทแแแถแแแแแแผแแแถแแแแฝแ!",
+ "pin":"แแแแปแแแแแถแแแถแแแแแแปแแ แพแ!",
+ "unpin":"แแแแปแแแแแทแแแถแแแแแแผแแแถแแแถแแแแแแปแ!",
+ "add":"แขแแแแแแแพแแแแถแแแแแแขแถแ
แ
แผแแแแแพแแแแปแแแแ แพแ!",
+ "remove":"แแทแแขแถแ
แแแขแแแแแแแพแแแแถแแแแแแ
แแแแธแแแแปแแแ!"
+ }
+ },
+ "params":{
+ "uppercase":{
+ "ticket":"แแแแปแแแ",
+ "tickets":"แแแแปแแแ",
+ "reason":"แแผแแ แแแป",
+ "creator":"แขแแแแแแแแพแ",
+ "remaining":"แแแแแแแถแแ
แแแ",
+ "added":"แแแแแแ",
+ "removed":"แแ",
+ "filter":"แแแแแ",
+ "method":"แแทแแธแแถแแแแแ",
+ "type":"แแแแแแ",
+ "blacklisted":"แแแแปแแแแแแธแแแแ
",
+ "panel":"Panel",
+ "command":"แแถแแแแแแแแถ",
+ "system":"แแแแแแแแ",
+ "true":"แแทแ",
+ "false":"แแทแแแทแ",
+ "syntax":"แแถแแแแแแแแแแแ",
+ "originalName":"แแแแแแแพแ",
+ "newName":"แแแแแแแแแธ",
+ "until":"แแ แผแแแแ",
+ "validOptions":"แแแแแพแแแแแนแแแแแผแ",
+ "validPanels":"Panel แแแแนแแแแแผแ",
+ "autoclose":"Autoclose",
+ "autodelete":"Autodelete",
+ "startupDate":"แแถแแแแทแ
แแแแแ
แถแแแแแแพแ",
+ "version":"แแแแ",
+ "name":"แแแแแ",
+ "role":"แแฝแแถแแธ",
+ "status":"แแแแถแแแถแ",
+ "claimed":"แแแฝแแ แพแ",
+ "pinned":"แแถแแแแแแปแแ แพแ",
+ "creationDate":"แแถแแแแทแ
แแแแแแแแแพแ",
+
+ "noone":"แแแแถแแแแแถ",
+ "open":"แแพแ",
+ "closed":"แแทแ",
+ "priority":"แขแถแแทแแถแ",
+ "participants":"แขแแแแ
แผแแแฝแ",
+ "yes":"แแถแ/แ
แถแ",
+ "no":"แแ",
+ "option":"แแแแแพแ",
+ "topic":"แแแแแถแแแ",
+ "uptime":"แแแแแแแพแแแถแแแแแแแแแ",
+ "messages":"แแถแ",
+ "embeds":"Embeds",
+ "files":"แฏแแแถแ",
+ "components":"แแถแแป",
+ "cooldown":"แแแแแแแแแแแถแแ",
+ "maxTickets":"แแแแปแแแแ
แแแพแแแแแปแ",
+ "admins":"แขแแแแแแแแแแแแ",
+ "roles":"แแฝแแถแแธ",
+ "size":"แแแ แ"
+ },
+ "lowercase":{
+ "text":"แขแแแแ",
+ "html":"html",
+ "command":"แแถแแแแแแแแถ",
+ "modal":"modal",
+ "button":"แแแผแแปแ",
+ "dropdown":"dropdown",
+ "method":"แแทแแธแแถแแแแแ"
+ }
+ },
+ "commands":{
+ "reason":"แแแแแถแแแแผแแ แแแปแแแแแ
แ
แทแแแแแแแแนแแแแแ แถแแแแแปแ logsแ",
+ "help":"แแแฝแแแถแแแแแแธแแถแแแแแแแแถแแแแแถแแ",
+ "panel":"แแแแ แถแแแถแแแถแแฝแ dropdown แฌ buttons (แแแแแถแแแแถแแแแแแพแแแแแปแแแ)แ",
+ "panelId":"แขแแแแแแแแแขแแแแแแแแถแ panel แแแแขแแแแ
แแแแแแ แถแแ",
+ "panelAutoUpdate":"แแพแขแแแแ
แแ panel แแแแแแแพแแ
แแ
แปแแแแแแแแถแแแแแแแแแแแแแแแแแท แแ
แแแแแแแแแ?",
+ "ticket":"แแแแแพแแแแแปแแแแแแแถแแแ",
+ "ticketId":"แขแแแแแแแแแขแแแแแแแแถแแแแแปแแแแแแแขแแแแ
แแแแแแแพแแ",
+ "close":"แแทแแแแแปแแแแ",
+ "delete":"แแปแแแแแปแแแแ",
+ "deleteNoTranscript":"แแปแแแแแปแแแแแแแแแแแแแถแแแถแแแแแแพแ transcriptแ",
+ "reopen":"แแพแแแแแปแแแแกแพแแแทแแ",
+ "claim":"แแแฝแแแแแปแแแแ",
+ "claimUser":"แแแฝแแแแแปแแแแแแแแ
แฑแแแแแแถแแแแถแแแแแแแแแแ แแแแฝแแขแแแแ",
+ "unclaim":"แแแแแแฝแแแแแปแแแแ",
+ "pin":"แแถแแแแแแปแแแแแปแแแแ",
+ "unpin":"แแแแแแปแแแแแปแแแแ",
+
+ "move":"แแแแถแแแแแแผแแแแแปแแแแ",
+ "moveId":"แขแแแแแแแแแขแแแแแแแแถแแแแแแพแแแแแขแแแแ
แแแแแแถแแแแแแผแแแ
แ",
+ "rename":"แแแแผแแแแแแแแแแปแแแแ",
+ "renameName":"แแแแแแแแแธแแแแแถแแแแแแปแแแแแแแ",
+ "add":"แแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแปแแแแ",
+ "addUser":"แขแแแแแแแพแแแแถแแแแแแแแแผแแแแแแแแ",
+ "remove":"แแแขแแแแแแแพแแแแถแแแ
แแแแธแแแแปแแแแ",
+ "removeUser":"แขแแแแแแแพแแแแถแแแแแแแแแผแแแแ",
+
+ "blacklist":"แแแแแแแแแแแแแแธแแแแ
แแแแปแแแแ",
+ "blacklistView":"แแพแแแแแแธแแแแแธแแแแ
แแ
แแ
แปแแแแแแแ",
+ "blacklistAdd":"แแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแแธแแแแ
แ",
+ "blacklistRemove":"แแแขแแแแแแแพแแแแถแแแ
แแแแธแแแแแธแแแแ
แ",
+ "blacklistGet":"แแแฝแแแถแแแแแแแถแแแแแขแทแแแธแขแแแแแแแพแแแแถแแแแแแปแแแแแแธแแแแ
แ",
+ "blacklistGetUser":"แขแแแแแแแพแแแแถแแแแแแแแแผแแแแฝแแแแแแแถแแแแแขแทแแ",
+ "stats":"แแพแแแแแทแแทแแธแแผแ, แแแถแแทแ แฌแแแแปแแแแ",
+ "statsReset":"แแแแแแแแแทแแทแแผแแแถแแแขแแแกแพแแแทแ (แ
แถแแแแแแพแแแถแแแแธแแผแแแ)แ",
+ "statsGlobal":"แแพแแแแแทแแทแแแปแแ",
+ "statsUser":"แแพแแแแแทแแทแแธแขแแแแแแแพแแแแถแแแแแแปแแแแถแแแธแแแแแแพแ",
+ "statsUserUser":"แขแแแแแแแพแแแแถแแแแแแแแแผแแแพแแ",
+ "statsTicket":"แแพแแแแแทแแทแแธแแแแปแแแแแแแปแแแแถแแแธแแแแแแพแ",
+ "statsTicketTicket":"แแแแปแแแแแแแแแแผแแแพแแ",
+
+ "clear":"แแปแแแแแปแแแแ
แแแพแแแแแปแแแแแแแแฝแแ",
+ "clearFilter":"แแแแแแแแแแถแแแแถแแแแแขแถแแแแแปแแแแ",
+ "clearFilters":{
+ "all":"แแถแแแขแแ",
+ "open":"แแพแ",
+ "close":"แแทแ",
+ "claim":"แแแฝแแ แพแ",
+ "unclaim":"แแทแแแถแแแแแฝแ",
+ "pin":"แแถแแแแแแปแแ แพแ",
+ "unpin":"แแทแแแถแแแแถแแแแแแปแ",
+ "autoclose":"แแทแแแแแแแแแแแแแแแแแท"
+ },
+
+ "autoclose":"แแแแแแแแแ autoclose แแแแปแแแแแปแแแแ",
+ "autocloseDisable":"แแทแ autoclose แแแแปแแแแแปแแแแแแแ",
+ "autocloseEnable":"แแพแ autoclose แแแแปแแแแแปแแแแแแแ",
+ "autocloseEnableTime":"แ
แแแฝแแแแแแแแแแแแปแแแแแแแแแแผแแแทแแแแแแ แแพแแแแธแแทแแ",
+ "autodelete":"แแแแแแแแแ autodelete แแแแปแแแแแปแแแแ",
+ "autodeleteDisable":"แแทแ autodelete แแแแปแแแแแปแแแแแแแ",
+ "autodeleteEnable":"แแพแ autodelete แแแแปแแแแแปแแแแแแแ",
+ "autodeleteEnableTime":"แ
แแแฝแแแแแแแแแแแแปแแแแแแแแแแผแแแทแแแแแแ แแพแแแแธแแปแแ",
+
+ "topic":"แแแแแแแแแแแแแแถแแแแแแแแถแแแแแปแแแแ",
+ "topicSet":"แแแแแแแแแแถแแแแแแแแถแแแแแปแแแแ",
+ "topicValue":"แแแแแถแแแแแแแธแแแแแแแแแถแแ",
+ "topicList":"แแแฝแแแถแแแแแแธแแแแปแแแแแถแแแขแแ แแถแแฝแแแแแแถแแแ แแทแแแแแทแแทแ",
+ "priority":"แแแแแแแแแแขแถแแทแแถแแแแแปแแแแ",
+ "prioritySet":"แแแแแแขแถแแทแแถแแแแแปแแแแ",
+ "priorityValue":"แขแถแแทแแถแแแแแแแแแแถแแ",
+ "priorityGet":"แแแฝแแแถแแขแถแแทแแถแแแแแปแแแแ",
+ "priorityList":"แแแฝแแแถแแแแแแธแแแแปแแแแแถแแแขแแ แแถแแฝแแแแแถแแแถแแขแถแแทแแถแแ",
+ "transfer":"แแแแแแแถแแแถแแแ
แถแแแแแแปแแแแแธแขแแแแแแแพแแแแถแแแแแแถแแแแ
แแแแถแแแแแแ",
+ "transferUser":"แขแแแแแแแพแแแแถแแแแแแแแแผแแแแแแแแ
แ"
+ },
+ "helpMenu":{
+ "help":"แแแฝแแแถแแแแแแธแแถแแแแแแแแถแแแแแถแแ",
+ "ticket":"แแแแแพแแแแแปแแแแแแแถแแแ",
+ "close":"แแทแแแแแปแแแ, แแทแแธแแแแแทแแแถแแแแแแแแแแปแแแแแแถแแ",
+ "delete":"แแปแแแแแปแแแ, แแทแแธแแแแแแแแพแ transcript แแ
แแแแแพแแ",
+ "reopen":"แแพแแแแแปแแแแกแพแแแทแ, แแทแแธแแแแแพแแแถแแแแแแแแแแปแแแแแแถแแแแแแแแแ",
+ "pin":"แแถแแแแแแปแแแแแปแแแแ แแถแแนแแแแแถแแแแแแปแแแแแ
แแถแแแพ แ แพแแแแแแแ '๐' แแ
แแแแแแ",
+ "unpin":"แแแแแแปแแแแแปแแแแ แแแแปแแแแแนแแแ
แแแแแแแแแ แแแปแแแแแแนแแแถแแ '๐'แ",
+ "move":"แแแแถแแแแแแผแแแแแปแแแแ แแถแแนแแแแแผแแแแแแแแแแแแแแแปแแแแ",
+ "rename":"แแแแผแแแแแแแแแแปแแแแ แแถแแนแแแแแผแแแแแแแแแแแถแแแแแแแแแปแแแแ",
+ "claim":"แแแฝแแแแแปแแแแ แแแแแทแแธแแแ แขแแแแขแถแ
แแแแถแแแแแแปแแแแแแขแแแแแถแขแแแแแแแปแแแแแแแแถแแแแแปแแแแแแแ",
+ "unclaim":"แแแแแแฝแแแแแปแแแแ แแแแแทแแธแแแ แขแแแแขแถแ
แแแแถแแแแแแปแแแแแแขแแแแแถแแแแปแแแแแแแแแแแแ",
+ "add":"แแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแปแแแแ แแถแแนแแขแแปแแแแถแแฑแแแขแแแแแแแพแแแแถแแแขแถแแแทแแแแแแแแแแปแแแแแปแแแแ",
+ "remove":"แแแขแแแแแแแพแแแแถแแแ
แแแแธแแแแปแแแแ แแถแแนแแแแแทแแแแทแขแถแแแทแแแแแแแแแแแขแแแแแแแพแแแแถแแแแแแปแแแแแปแแแแ",
+ "panel":"แแแแ แถแแแถแแแถแแฝแ dropdown แฌ buttons (แแแแแถแแแแถแแแแแแพแแแแแปแแแ)แ",
+ "blacklistView":"แแพแแแแแแธแแแแแธแแแแ
แแ
แแ
แปแแแแแแแ",
+ "blacklistAdd":"แแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแแธแแแแ
แ",
+ "blacklistRemove":"แแแขแแแแแแแพแแแแถแแแ
แแแแธแแแแแธแแแแ
แ",
+ "blacklistGet":"แแแฝแแแถแแแแแแแถแแแแแขแทแแแธแขแแแแแแแพแแแแถแแแแแแปแแแแแแธแแแแ
แ",
+ "statsGlobal":"แแพแแแแแทแแทแแแปแแ",
+ "statsTicket":"แแพแแแแแทแแทแแธแแแแปแแแแแแแปแแแแถแแแธแแแแแแพแ",
+ "statsUser":"แแพแแแแแทแแทแแธแขแแแแแแแพแแแแถแแแแแแปแแแแถแแแธแแแแแแพแ",
+ "statsReset":"แแแแแแแแแทแแทแแผแแแถแแแขแแแกแพแแแทแ (แ
แถแแแแแแพแแแถแแแแธแแผแแแ)แ",
+ "autocloseDisable":"แแทแ autoclose แแแแปแแแแแปแแแแแแแ",
+ "autocloseEnable":"แแพแ autoclose แแแแปแแแแแปแแแแแแแ",
+ "autodeleteDisable":"แแทแ autodelete แแแแปแแแแแปแแแแแแแ",
+ "autodeleteEnable":"แแพแ autodelete แแแแปแแแแแปแแแแแแแ",
+ "categories":{
+ "general":"แแถแแแแแแแแถแแผแแ
",
+ "basicTicket":"แแถแแแแแแแแถแแแแปแแแแแผแแแแแถแ",
+ "advancedTicket":"แแถแแแแแแแแถแแแแปแแแแแแแแทแแแแแแ",
+ "userTicket":"แแถแแแแแแแแถแแแแปแแแแขแแแแแแแพแแแแถแแ",
+ "admin":"แแถแแแแแแแแถ Admin",
+ "advanced":"แแถแแแแแแแแถแแแแแทแแแแแแ",
+ "extra":"แแถแแแแแแแแถแแแแแแ"
+ }
+ },
+ "stats":{
+ "scopes":{
+ "global":"แแแแทแแทแแแปแ",
+ "system":"แแแแทแแทแแแแแแแแ",
+ "user":"แแแแทแแทแขแแแแแแแพแแแแถแแ",
+ "ticket":"แแแแทแแทแแแแปแแแ",
+ "participants":"แขแแแแ
แผแแแฝแ",
+ "messages":"แแถแ"
+ },
+ "properties":{
+ "ticketsCreated":"แแแแปแแแแแถแแแแแแพแ",
+ "ticketsClosed":"แแแแปแแแแแถแแแทแ",
+ "ticketsDeleted":"แแแแปแแแแแถแแแปแ",
+ "ticketsReopened":"แแแแปแแแแแถแแแพแแกแพแแแทแ",
+ "ticketsAutoclosed":"แแแแปแแแแแถแแแทแแแแแแแแแแแแแแแแแท",
+ "ticketsClaimed":"แแแแปแแแแแถแแแแฝแ",
+ "ticketsPinned":"แแแแปแแแแแถแแแถแแแแแแปแ",
+ "ticketsMoved":"แแแแปแแแแแถแแแแแถแแแแแแผแ",
+ "usersBlacklisted":"แขแแแแแแแพแแแแถแแแแแแปแแแแแแธแแแแ
",
+ "transcriptsCreated":"Transcript แแถแแแแแแพแ",
+ "ticketsAutodeleted":"แแแแปแแแแแถแแแปแแแแแแแแแแแแแแแแแท",
+ "ticketsTransferred":"แแแแปแแแแแถแแแแแแ",
+ "ticketVolume":"แ
แแแฝแแแแแปแแแ",
+ "averageTickets":"แ
แแแฝแแแแแปแแแแแถแแแแแ/แขแแแแแแแพ",
+ "currentTickets":"แแแแปแแแแแ
แแ
แปแแแแแแ",
+ "age":"แขแถแแปแแแแปแแแ",
+ "responseTime":"แแแแแแแพแแแ",
+ "resolutionTime":"แแแแแแแแแแถแ",
+ "createdOn":"แแแแแพแแแ
",
+ "createdBy":"แแแแแพแแแแ",
+ "closedOn":"แแทแแแ
",
+ "closedBy":"แแทแแแแ",
+ "claimedOn":"แแแฝแแแ
",
+ "claimedBy":"แแแฝแแแแ",
+ "pinnedOn":"แแถแแแแแแปแแแ
",
+ "pinnedBy":"แแถแแแแแแปแแแแ",
+ "deletedOn":"แแปแแแ
",
+ "deletedBy":"แแปแแแแ"
+ },
+ "roles":{
+ "developer":"Developer",
+ "serverOwner":"แแแ
แถแแแแแถแแแธแแแแแแพ",
+ "serverAdmin":"Admin แแแถแแแธแแแแแแพ",
+ "moderator":"แแแแปแแขแแแแแแแแปแแแแแแฝแ",
+ "support":"แแแแปแแแแแฝแ",
+ "member":"แแแถแแทแ"
+ }
+ },
+ "panel":{
+ "selectTicket":"แแแแพแแแพแแแแแปแแแแแแแแขแแแ",
+ "selectRole":"แแแแพแแแพแแแฝแแถแแธแแแแแขแแแ",
+ "selectOption":"แแแแพแแแพแแแแแแพแแแแแแขแแแ"
+ },
+ "priorities":{
+ "urgent":"แแแแแถแแแแแแถแแ",
+ "veryHigh":"แแแแแแแถแแ",
+ "high":"แแแแแ",
+ "normal":"แแแแแแถ",
+ "low":"แแถแ",
+ "veryLow":"แแถแแแถแแ",
+ "none":"แแแแถแ"
}
- },
- "actions": {
- "buttons": {
- "create": "แ
แผแแแพแแแแแปแแแ",
- "close": "แแทแแแแแปแแแ",
- "delete": "แแปแแแแแปแแแ",
- "reopen": "แแพแแแแแปแแแแกแพแแแทแ",
- "claim": "แแแฝแแแแแปแแแ",
- "unclaim": "แแแแแแฝแแแแแปแแแ",
- "pin": "แแถแแแแแแปแแแแแปแแแ",
- "unpin": "แแแแแแปแแแแแปแแแ",
- "clear": "แแปแแแแแปแแแแแถแแแขแแ",
- "helpSwitchSlash": "แแพแแแถแแแแแแแแถ Slash",
- "helpSwitchText": "แแพแแแถแแแแแแแแถแขแแแแ",
- "helpPage": "แแแแแ {0}",
- "withReason": "แแถแแฝแแ แแแปแแ",
- "withoutTranscript": "แแแแถแ Transcript"
- },
- "titles": {
- "created": "แแถแแแแแแพแแแแแปแแแ",
- "close": "แแถแแแทแแแแแปแแแ",
- "delete": "แแถแแแปแแแแแปแแแ",
- "reopen": "แแถแแแพแแแแแปแแแแกแพแแแทแ",
- "claim": "แแถแแแแฝแแแแแปแแแ",
- "unclaim": "แแถแแแแแแแฝแแแแแปแแแ",
- "pin": "แแถแแแถแแแแแแปแแแแแปแแแ",
- "unpin": "แแถแแแแแแแปแแแแแปแแแ",
- "rename": "แแถแแแแแผแแแแแแแแแแปแแแ",
- "move": "แแถแแแแแถแแแแแแผแแแแแปแแแ",
- "add": "แแถแแแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแปแแแ",
- "remove": "แแถแแแแขแแแแแแแพแแแแถแแแแธแแแแปแแแ",
-
- "help": "แแถแแแแแแแแถแแแแแถแ",
- "statsReset": "แแแแแแแแแทแแทแกแพแแแทแ",
- "blacklistAdd": "แขแแแแแแแพแแแแถแแแแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
",
- "blacklistRemove": "แขแแแแแแแพแแแแถแแแแแแผแแแถแแแแแแแ",
- "blacklistGet": "แขแแแแแแแพแแแแถแแแแแแปแแแแแแธแแแแ
",
- "blacklistView": "แแแแแธแแแแ
แแ
แแ
แปแแแแแแ",
- "blacklistAddDm": "แแแแผแแแถแแแแแแแแแ
แแแแแธแแแแ
",
- "blacklistRemoveDm": "แแแแผแแแถแแแแ
แแแแธแแแแแธแแแแ
",
- "clear": "แแถแแแแแขแถแแแแแปแแแ",
- "clearTickets": "แแแแขแถแแแแแปแแแ",
- "roles": "แแฝแแถแแธแแถแแแแแพแแ
แแ
แปแแแแแแแแถแ",
-
- "autoclose": "แแแแปแแแแแถแแแทแแแแแแแแแแแแแแแแแท",
- "autocloseEnabled": "แแถแแแพแ Autoclose",
- "autocloseDisabled": "แแถแแแทแ Autoclose",
- "autodelete": "แแแแปแแแแแถแแแปแแแแแแแแแแแแแแแแแท",
- "autodeleteEnabled": "แแถแแแพแ Autodelete",
- "autodeleteDisabled": "แแถแแแทแ Autodelete",
-
- "topicSet": "แแถแแแแแผแแแแแแถแแแ",
- "prioritySet": "แแถแแแแแผแแขแถแแทแแถแ",
- "priorityGet": "แขแถแแทแแถแแแแแปแแแ",
- "transfer": "แแถแแแแแแแแแแปแแแ"
- },
- "descriptions": {
- "create": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแแพแแ แ
แปแ
แแแผแแปแแแถแแแแแแแแพแแแแธแ
แผแแแแแพ!",
- "close": "แแแแปแแแแแแแผแแแถแแแทแแแแแแแแแแ!",
- "delete": "แแแแปแแแแแแแผแแแถแแแปแแแแแแแแแแ!",
- "reopen": "แแแแปแแแแแแแผแแแถแแแพแแกแพแแแทแแแแแแแแแแ!",
- "claim": "แแแแปแแแแแแแผแแแถแแแแฝแแแแแแแแแแ!",
- "unclaim": "แแแแปแแแแแแแผแแแถแแแแแแแฝแแแแแแแแแแ!",
- "pin": "แแแแปแแแแแแแผแแแถแแแถแแแแแแปแแแแแแแแแแ!",
- "unpin": "แแแแปแแแแแแแผแแแถแแแแแแแปแแแแแแแแแแ!",
- "rename": "แแแแปแแแแแแแผแแแถแแแแแผแแแแแแแแ
{0} แแแแแแแแแ!",
- "move": "แแแแปแแแแแแแผแแแถแแแแแถแแแแแแผแแแ
{0} แแแแแแแแแ!",
- "add": "{0} แแแแผแแแถแแแแแแแแแ
แแแแปแแแแแแแแแแแแ!",
- "remove": "{0} แแแแผแแแถแแแแ
แแแแธแแแแปแแแแแแแแแแแแ!",
-
- "helpExplanation": "`` => แแแถแแแถแแแแแแแ
แถแแแถแ
แ\n`[name]` => แแแถแแแถแแแแแแแแแแแ
แ
แทแแแ",
- "statsReset": "แแแแทแแทแแผแแแแแผแแแถแแแแแแแกแพแแแทแแแแแแแแแแ!",
- "statsError": "แแทแแขแถแ
แแพแแแแแทแแทแแแแปแแแ!\n{0} แแทแแแแแแถแแแแปแแแ!",
- "blacklistAdd": "{0} แแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
แแแแแแแแแ!",
- "blacklistRemove": "{0} แแแแผแแแถแแแแแแแแแแแแแแแแ!",
- "blacklistGetSuccess": "{0} แแแแทแแแแแปแแแแแแธแแแแ
แแ
แแ
แปแแแแแแ!",
- "blacklistGetEmpty": "{0} แแทแแแแแทแแแแแปแแแแแแธแแแแ
แแ
แแ
แปแแแแแแ!",
- "blacklistViewEmpty": "แแทแแแถแแแแถแแขแแแแแถแแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
!",
- "blacklistViewTip": "แแแแพ \"/blacklist add\" แแพแแแแธแแถแแแขแแแแแแแพแแแแปแแแแแแธแแแแ
!",
- "clearVerify": "แแพแขแแแแแแแถแแแแถแ
แแแแปแแแแแปแแแแ
แแแพแ?\nแแแแแแแถแแแแแแทแแขแถแ
แแแแกแแแแแแทแ!",
- "clearReady": "แแแแปแแแ {0} แแแแผแแแถแแแปแแแแแแแแแแ!",
- "rolesEmpty": "แแทแแแถแแแฝแแถแแธแแถแแแแผแแแถแแแแแพแแ
แแ
แปแแแแแแแแถแ!",
-
- "autocloseLeave": "แแแแปแแแแแแแแแแผแแแถแแแทแแแแแแแแแแแแแแแแแท แแแแแถแแขแแแแแแแแพแแแถแแ
แถแแ
แแแแธแแแถแแแธแแแแแแพ!",
- "autocloseTimeout": "แแแแปแแแแแแแแแแผแแแถแแแทแแแแแแแแแแแแแแแแแท แแแแแถแแแถแแทแแแแแแแแพแแแธ `{0}h`!",
- "autodeleteLeave": "แแแแปแแแแแแแแแแผแแแถแแแปแแแแแแแแแแแแแแแแแท แแแแแถแแขแแแแแแแแพแแแถแแ
แถแแ
แแแแธแแแถแแแธแแแแแแพ!",
- "autodeleteTimeout": "แแแแปแแแแแแแแแแผแแแถแแแปแแแแแแแแแแแแแแแแแท แแแแแถแแแถแแทแแแแแแแแพแแแธ `{0} แแแแ`!",
- "autocloseEnabled": "Autoclose แแแแผแแแถแแแพแแแแแปแแแแแปแแแแแแ!\nแแถแแนแแแแแผแแแถแแแทแแแ
แแแแแทแแแแแแแแพแแแธ `{0}h`!",
- "autocloseDisabled": "Autoclose แแแแผแแแถแแแทแแแแแปแแแแแปแแแแแแ!\nแแถแแนแแแทแแแแแผแแแถแแแทแแแแแแแแแแแแแแแแแทแแแแแ!",
- "autodeleteEnabled": "Autodelete แแแแผแแแถแแแพแแแแแปแแแแแปแแแแแแ!\nแแถแแนแแแแแผแแแถแแแปแแแ
แแแแแทแแแแแแแแพแแแธ `{0} แแแแ`!",
- "autodeleteDisabled": "Autodelete แแแแผแแแถแแแทแแแแแปแแแแแปแแแแแแ!\nแแถแแนแแแทแแแแแผแแแถแแแปแแแแแแแแแแแแแแแแแทแแแแแ!",
-
- "ticketMessageLimit": "แขแแแแขแถแ
แแแแแพแแแแแปแแแ {0} แแแแปแแแแแแแแฝแ!",
- "ticketMessageAutoclose": "แแแแปแแแแแแแแนแแแแแผแแแถแแแทแแแแแแแแแแแแแแแแแท แแ
แแแแแทแแแแแแ {0}h!",
- "ticketMessageAutodelete": "แแแแปแแแแแแแแนแแแแแผแแแถแแแปแแแแแแแแแแแแแแแแแท แแ
แแแแแทแแแแแแ {0} แแแแ!",
- "panelReady": "Panel แแถแแแ
แแแแปแแแถแแแแแ!\nแแถแแแแแขแถแ
แแปแแแถแแ แพแ!",
-
- "topicSet": "แแแแแถแแแแแแแแถแแแแแผแแแถแแแแแผแแแแ {0} แแแแแแแแแ!",
- "prioritySet": "แขแถแแทแแถแแแแแปแแแแแแแผแแแถแแแแแผแแแ
{0} แแแ {1} แแแแแแแแแ!",
- "priorityGet": "แขแถแแทแแถแแแ
แแ
แปแแแแแแแแแแแแแแปแแแแแแแแบ {0}แ",
- "transfer": "แแถแแแถแแแ
แถแแแแแแปแแแแแแแผแแแถแแแแแแแแธ {0} แแ
{1} แแแ {2} แแแแแแแแแ!"
- },
- "modal": {
- "closePlaceholder": "แ แแแปแขแแแธแขแแแแแทแแแแแปแแแแแแ?",
- "deletePlaceholder": "แ แแแปแขแแแธแขแแแแแปแแแแแปแแแแแแ?",
- "reopenPlaceholder": "แ แแแปแขแแแธแขแแแแแพแแแแแปแแแแแแแกแพแแแทแ?",
- "claimPlaceholder": "แ แแแปแขแแแธแขแแแแแแฝแแแแแปแแแแแแ?",
- "unclaimPlaceholder": "แ แแแปแขแแแธแขแแแแแแแแแฝแแแแแปแแแแแแ?",
- "pinPlaceholder": "แ แแแปแขแแแธแขแแแแแถแแแแแแปแแแแแปแแแแแแ?",
- "unpinPlaceholder": "แ แแแปแขแแแธแขแแแแแแแแแปแแแแแปแแแแแแ?"
- },
- "logs": {
- "createLog": "แแแแปแแแแแแแธแแแแผแแแถแแแแแแพแแแแ {0}!",
- "closeLog": "แแแแปแแแแแแแแแแผแแแถแแแทแแแแ {0}!",
- "closeDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแทแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "deleteLog": "แแแแปแแแแแแแแแแผแแแถแแแปแแแแ {0}!",
- "deleteDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแปแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "reopenLog": "แแแแปแแแแแแแแแแผแแแถแแแพแแกแพแแแทแแแแ {0}!",
- "reopenDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแพแแกแพแแแทแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "claimLog": "แแแแปแแแแแแแแแแผแแแถแแแแฝแแแแ {0}!",
- "claimDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแฝแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "unclaimLog": "แแแแปแแแแแแแแแแผแแแถแแแแแแแฝแแแแ {0}!",
- "unclaimDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแแแฝแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "pinLog": "แแแแปแแแแแแแแแแผแแแถแแแถแแแแแแปแแแแ {0}!",
- "pinDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแถแแแแแแปแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "unpinLog": "แแแแปแแแแแแแแแแผแแแถแแแแแแแปแแแแ {0}!",
- "unpinDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแแแปแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "renameLog": "แแแแปแแแแแแแแแแผแแแถแแแแแผแแแแแแแแ
{0} แแแ {1}!",
- "renameDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแผแแแแแแแแ
{0} แแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "moveLog": "แแแแปแแแแแแแแแแผแแแถแแแแแถแแแแแแผแแแ
{0} แแแ {1}!",
- "moveDm": "แแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแถแแแแแแผแแแ
{0} แแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "addLog": "{0} แแแแผแแแถแแแแแแแแแ
แแแแปแแแแแแแแแ {1}!",
- "addDm": "{0} แแแแผแแแถแแแแแแแแแ
แแแแปแแแแแแแแขแแแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "removeLog": "{0} แแแแผแแแถแแแแ
แแแแธแแแแปแแแแแแแแแ {1}!",
- "removeDm": "{0} แแแแผแแแถแแแแ
แแแแธแแแแปแแแแแแแแขแแแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
-
- "blacklistAddLog": "{0} แแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
แแแ {1}!",
- "blacklistRemoveLog": "{0} แแแแผแแแถแแแแ
แแแแธแแแแแธแแแแ
แแแ {1}!",
- "blacklistAddDm": "แขแแแแแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!\nแ
แถแแแแธแแแแแแ แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ!",
- "blacklistRemoveDm": "แขแแแแแแแผแแแถแแแแ
แแแแธแแแแแธแแแแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!\nแฅแกแผแแขแแแแขแถแ
แแแแแพแแแแแปแแแแแถแแแแแแแแ!",
- "clearLog": "แแแแปแแแ {0} แแแแผแแแถแแแปแแแแ {1}!",
-
- "transferLog": "แแถแแแถแแแ
แถแแแแแแปแแแแแแแแแแผแแแถแแแแแแแแธ {0} แแ
{1} แแแ {2}!",
- "transferDm": "แแถแแแถแแแ
แถแแแแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแแแแธ {0} แแ
{1} แแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "prioritySetLog": "แขแถแแทแแถแแแแแปแแแแแแแแแแผแแแถแแแแแผแแแ
{0} แแแ {1}!",
- "prioritySetDm": "แขแถแแทแแถแแแแแปแแแแแแแแขแแแแแแแผแแแถแแแแแผแแแ
{0} แแ
แแแแปแแแแถแแแธแแแแแแพแแแแแแพแ!",
- "roleUpdateLog": "{0} แแถแแแแแพแแ
แแ
แปแแแแแแแแถแแแฝแแถแแธแแแแแแแแฝแ!",
- "roleUpdateDm": "แแฝแแถแแธแแแแแขแแแแแแแปแแแแถแแแธแแแแแแพแแแแแแพแแแแแผแแแถแแแแแพแแ
แแ
แปแแแแแแแแถแ!"
- }
- },
- "transcripts": {
- "success": {
- "visit": "แ
แผแแแพแ Transcript",
- "ready": "Transcript แแแแผแแแถแแแแแแพแ",
- "textFileDescription": "แแแแแถ transcript แขแแแแแแแแแแแแปแแแแแแแแถแแแปแ!",
- "htmlProgress": "แแผแแแแแ
แถแ แแแ html transcript แแแแปแแแแแผแแแถแแแแแพแแแถแ...",
-
- "createdChannel": "transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแปแแแแถแแแธแแแแแแพ!",
- "createdCreator": "transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแแถแแแแแแปแแแแแแแแขแแแ!",
- "createdParticipant": "transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแปแแแแแปแแแแแแแขแแแแแถแแ
แผแแแฝแ!",
- "createdActiveAdmin": "transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแปแแแแแปแแแแแแแขแแแแแถแแ
แผแแแฝแแแถแขแแแแแแแแแแแแ!",
- "createdEveryAdmin": "transcript {0} แแแแธแแแแผแแแถแแแแแแพแแแแแปแแแแแปแแแแแแแขแแแแแถแขแแแแแแแแแแแแ!",
- "createdOther": "transcript {0} แแแแธแแแแผแแแถแแแแแแพแ!"
- },
- "errors": {
- "retry": "แแแแถแแถแแแแแแแแ",
- "continue": "แแปแแแแแแแแถแ Transcript",
- "backup": "แแแแแพแ Transcript แแแแแปแ",
- "error": "แแถแแแแแ แถแแแแแแแแปแแแถแแแแแแพแ transcriptแ\nแขแแแแ
แแแแแแพแขแแแธ?\n\nแแแแปแแแแแแแแนแแแทแแแแแผแแแถแแแปแแแ แแ แผแแขแแแแ
แปแ
แแแผแแปแแแถแแฝแแ",
- "title": "แแแ แปแ Transcript"
- },
- "text": {
- "messagesTitle": "แแถแ",
- "embedTitle": "EMBED",
- "fileTitle": "แฏแแแถแ",
- "fieldsTitle": "แแถแ",
- "reactionsTitle": "แแแแแทแแแแ",
- "statsTitle": "แแแแทแแท",
- "emptyContent": "<แแถแแทแแถแแแ>",
- "noTitle": "<แแแแถแแ
แแแแแพแ>",
- "noDesc": "<แแแแถแแแถแแแทแแแแแถ>"
- }
- },
- "errors": {
- "titles": {
- "internalError": "แแแ แปแแแแแแแแแปแ",
- "optionMissing": "แแแแแพแแแถแแแแแแแแถแแถแแ",
- "optionInvalid": "แแแแแพแแแถแแแแแแแแถแแทแแแแแนแแแแแผแ",
- "unknownCommand": "แแถแแแแแแแแถแแทแแแแแถแแ",
- "noPermissions": "แแแแถแแแทแแแแท",
- "unknownTicket": "แแแแปแแแแแทแแแแแถแแ",
- "deprecatedTicket": "แแแแปแแแแ แฝแแแแแ",
- "unknownOption": "แแแแแพแแแทแแแแแถแแ",
- "unknownPanel": "Panel แแทแแแแแถแแ",
- "notInGuild": "แแทแแแ
แแแแปแแแแถแแแธแแแแแแพ",
- "channelRename": "แแทแแขแถแ
แแแแผแแแแแแแแแแแถแ",
- "busy": "แแแแปแแแแแแแปแแแแแพแแแถแ",
- "permissionError": "แแแ แปแแแทแแแแท"
- },
- "descriptions": {
- "askForInfo": "แแแแถแแแแแแแแแ
แถแแแแผแแแแแแแแแถแแแแแแแแถแแแแแแแ!",
- "askForInfoResolve": "แแแแถแแแแแแแแแ
แถแแแแผแแแแ แแแแแทแแแพแแแแ แถแแแแแทแแแแแแแแถแแแแแแถแแแแธแแแแถแแถแแแฝแแ
แแแฝแแ",
- "internalError": "แแแถแแแแแแแปแแแถแแแแแพแแแ {0} แแแแแถแแแแ แปแแแแแแแแแปแ!",
- "optionMissing": "แแแถแแแถแแแแแแแ
แถแแแถแ
แแแแแแแแแปแแแถแแแแแแแแถแแแ!",
- "optionInvalid": "แแแถแแแถแแแแแแแแแแปแแแถแแแแแแแแถแแแแแทแแแแแนแแแแแผแ!",
- "optionInvalidChoose": "แแแแพแแแพแแแแถแ",
- "unknownCommand": "แแผแแ
แผแแแพแแแแบแแปแแแแแฝแแแแแแถแแแแแแแแถแแแแแแแ!",
- "noPermissions": "แขแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแแแพ {0} แแแ!",
- "noPermissionsList": "แแทแแแแทแแแแแแแผแแแถแ: (แแฝแแแแแปแแ
แแแแ)",
- "noPermissionsCooldown": "แขแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแแแพ {0} แแแ แแแแแถแแขแแแแแถแแแแแแแแแแแแถแแ!",
- "noPermissionsBlacklist": "แขแแแแแทแแแแแผแแแถแแขแแปแแแแถแแฑแแแแแแพ {0} แแแ แแแแแถแแขแแแแแแแผแแแถแแแถแแแแแแปแแแแแแธแแแแ
!",
- "noPermissionsLimitGlobal": "แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ แแแแแถแแแแถแแแธแแแแแแพแแถแแแแแแแแแแแแแแแแปแแแแ
แแแพแแแแแปแ!",
- "noPermissionsLimitGlobalUser": "แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ แแแแแถแแขแแแแแถแแแแแแแแแแแแแแแแปแแแแ
แแแพแแแแแปแ!",
- "noPermissionsLimitOption": "แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ แแแแแถแแแแถแแแธแแแแแแพแแถแแแแแแแแแแแแแแแแปแแแแ
แแแพแแแแแปแแแแแแถแแแแแแแพแแแแ!",
- "noPermissionsLimitOptionUser": "แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแ แแแแแถแแขแแแแแถแแแแแแแแแแแแแแแแปแแแแ
แแแพแแแแแปแแแแแแถแแแแแแแพแแแแ!",
- "unknownTicket": "แแผแแแถแแแแแแแถแแแแแแแแถแแแแแแแแแแแแแแปแแแแแปแแแแแแแนแแแแแผแ!",
- "deprecatedTicket": "แแแแแถแแแ
แแ
แปแแแแแแแแทแแแแแแถแแแแปแแแแแแแนแแแแแผแ! แแถแแแแ แแแแถแแแแปแแแแแธ Open Ticket แแแแแ
แถแแ!",
- "notInGuild": "{0} แแแแแทแแแแแพแแแถแแแแแปแ DM! แแผแแแถแแแแแแแแแแแแแแแแปแแแแถแแแธแแแแแแพ!",
- "channelRename": "แแแแแถแ discord ratelimits, แแถแแทแแขแถแ
แแ
แแถแแแแแแถแแแแผแแแแแปแแแถแแแแแผแแแแแแแแแแแถแแ แแแแแถแแแนแแแแแผแแแถแแแแแผแแแแแแแแแแแแแแแแแแแแแแท แแแแปแแแแแแแ 10 แแถแแธ แแแแแทแแแพแแผแแแทแแแถแแ
แถแแแแแแพแแกแพแแแทแแ",
- "channelRenameSource": "แแแแแแแแ แปแแแแแแบ: {0}",
- "busy": "แแทแแขแถแ
แแแแพ {0} แแแ!\nแแแแปแแแแแแแปแแแแแผแแแถแแแแแพแแแถแแแแแแผแแ\n\nแแผแแแแแถแแถแแแแแแแแแแแแปแแแธแแแธแแทแแถแแธ!",
- "closeBeforeMessage": "แแแแปแแแแแแแแทแแขแถแ
แแทแ/แแปแแแปแแแถแแแถแแแธแขแแแแแแแพแ",
- "closeBeforeAdminMessage": "แแแแปแแแแแแแแทแแขแถแ
แแทแ/แแปแแแปแแแถแแแถแแแธแขแแแแแแแแแแแแแแแแปแแแ แฌแแแถแแทแแแแแฝแแ",
- "unableToCreateTicket": "แขแแแแแทแแขแถแ
แแแแแพแแแแแปแแแแ"
- },
- "optionInvalidReasons": {
- "stringRegex": "แแแแแแแทแแแแแผแแแนแแแแแถแ!",
- "stringMinLength": "แแแแแแแแแผแแแถแแแแถแแ แแ
แแถแแ {0} แแฝแขแแแแ!",
- "stringMaxLength": "แแแแแแแแแผแแแถแแ
แแแพแแแแแปแ {0} แแฝแขแแแแ!",
- "numberInvalid": "แแแแแทแแแแแนแแแแแผแ!",
- "numberMin": "แแแแแแแผแแแถแแแแถแแ แแ
แแถแแ {0}!",
- "numberMax": "แแแแแแแผแแแถแแ
แแแพแแแแแปแ {0}!",
- "numberDecimal": "แแแแแทแแแแแผแแแถแแขแแปแแแแถแแแถแแแแถแ!",
- "numberNegative": "แแแแแทแแแแแผแแแถแแขแแปแแแแถแแแถแขแแทแแแแแถแ!",
- "numberPositive": "แแแแแทแแแแแผแแแถแแขแแปแแแแถแแแถแแทแแแแแถแ!",
- "numberZero": "แแแแแทแแแแแผแแแถแแขแแปแแแแถแแแถแแผแแแ!",
- "channelNotFound": "แแแแแแแถแแแทแแแพแ!",
- "userNotFound": "แแแขแแแแแแแพแแแแถแแแแทแแแพแ!",
- "roleNotFound": "แแแแฝแแถแแธแแทแแแพแ!",
- "memberNotFound": "แแแขแแแแแแแพแแแแถแแแแทแแแพแ!",
- "mentionableNotFound": "แแแขแแแแแแแพแแแแถแแ แฌแแฝแแถแแธแแทแแแพแ!",
- "channelType": "แแแแแแแแแแแถแแแทแแแแแนแแแแแผแ!",
- "notInGuild": "แแแแแพแแแแแแถแแแถแแฑแแแขแแแแแ
แแแแปแแแแถแแแธแแแแแแพ!"
- },
- "permissions": {
- "developer": "แขแแแแแแแผแแแถ developer แแแแแแผแแ",
- "owner": "แขแแแแแแแผแแแถแแแ
แถแแแแแถแแแธแแแแแแพแ",
- "admin": "แขแแแแแแแผแแแถ admin แแแถแแแธแแแแแแพแ",
- "moderator": "แขแแแแแแแผแแแถแขแแแแแแแแปแแแแแแฝแแ",
- "support": "แขแแแแแแแผแแแ
แแแแปแแแแแปแแแแแฝแแ",
- "member": "แขแแแแแแแผแแแถแแแถแแทแแ",
- "discord-administrator": "แขแแแแแแแผแแแถแแแทแแแแท `ADMINISTRATOR`แ"
- },
- "actionInvalid": {
- "close": "แแแแปแแแแแถแแแทแแ แพแ!",
- "reopen": "แแแแปแแแแแทแแแถแแแแทแ!",
- "claim": "แแแแปแแแแแถแแแแฝแแ แพแ!",
- "unclaim": "แแแแปแแแแแทแแแถแแแแแแผแแแถแแแแฝแ!",
- "pin": "แแแแปแแแแแถแแแถแแแแแแปแแ แพแ!",
- "unpin": "แแแแปแแแแแทแแแถแแแแแแผแแแถแแแถแแแแแแปแ!",
- "add": "แขแแแแแแแพแแแแถแแแแแแขแถแ
แ
แผแแแแแพแแแแปแแแแ แพแ!",
- "remove": "แแทแแขแถแ
แแแขแแแแแแแพแแแแถแแแแแแ
แแแแธแแแแปแแแ!"
- }
- },
- "params": {
- "uppercase": {
- "ticket": "แแแแปแแแ",
- "tickets": "แแแแปแแแ",
- "reason": "แแผแแ แแแป",
- "creator": "แขแแแแแแแแพแ",
- "remaining": "แแแแแแแถแแ
แแแ",
- "added": "แแแแแแ",
- "removed": "แแ",
- "filter": "แแแแแ",
- "method": "แแทแแธแแถแแแแแ",
- "type": "แแแแแแ",
- "blacklisted": "แแแแปแแแแแแธแแแแ
",
- "panel": "Panel",
- "command": "แแถแแแแแแแแถ",
- "system": "แแแแแแแแ",
- "true": "แแทแ",
- "false": "แแทแแแทแ",
- "syntax": "แแถแแแแแแแแแแแ",
- "originalName": "แแแแแแแพแ",
- "newName": "แแแแแแแแแธ",
- "until": "แแ แผแแแแ",
- "validOptions": "แแแแแพแแแแแนแแแแแผแ",
- "validPanels": "Panel แแแแนแแแแแผแ",
- "autoclose": "Autoclose",
- "autodelete": "Autodelete",
- "startupDate": "แแถแแแแทแ
แแแแแ
แถแแแแแแพแ",
- "version": "แแแแ",
- "name": "แแแแแ",
- "role": "แแฝแแถแแธ",
- "status": "แแแแถแแแถแ",
- "claimed": "แแแฝแแ แพแ",
- "pinned": "แแถแแแแแแปแแ แพแ",
- "creationDate": "แแถแแแแทแ
แแแแแแแแแพแ",
-
- "noone": "แแแแถแแแแแถ",
- "open": "แแพแ",
- "closed": "แแทแ",
- "priority": "แขแถแแทแแถแ",
- "participants": "แขแแแแ
แผแแแฝแ",
- "yes": "แแถแ/แ
แถแ",
- "no": "แแ",
- "option": "แแแแแพแ",
- "topic": "แแแแแถแแแ",
- "uptime": "แแแแแแแพแแแถแแแแแแแแแ",
- "messages": "แแถแ",
- "embeds": "Embeds",
- "files": "แฏแแแถแ",
- "components": "แแถแแป",
- "cooldown": "แแแแแแแแแแแถแแ",
- "maxTickets": "แแแแปแแแแ
แแแพแแแแแปแ",
- "admins": "แขแแแแแแแแแแแแ",
- "roles": "แแฝแแถแแธ",
- "size": "แแแ แ"
- },
- "lowercase": {
- "text": "แขแแแแ",
- "html": "html",
- "command": "แแถแแแแแแแแถ",
- "modal": "modal",
- "button": "แแแผแแปแ",
- "dropdown": "dropdown",
- "method": "แแทแแธแแถแแแแแ"
- }
- },
- "commands": {
- "reason": "แแแแแถแแแแผแแ แแแปแแแแแ
แ
แทแแแแแแแแนแแแแแ แถแแแแแปแ logsแ",
- "help": "แแแฝแแแถแแแแแแธแแถแแแแแแแแถแแแแแถแแ",
- "panel": "แแแแ แถแแแถแแแถแแฝแ dropdown แฌ buttons (แแแแแถแแแแถแแแแแแพแแแแแปแแแ)แ",
- "panelId": "แขแแแแแแแแแขแแแแแแแแถแ panel แแแแขแแแแ
แแแแแแ แถแแ",
- "panelAutoUpdate": "แแพแขแแแแ
แแ panel แแแแแแแพแแ
แแ
แปแแแแแแแแถแแแแแแแแแแแแแแแแแท แแ
แแแแแแแแแ?",
- "ticket": "แแแแแพแแแแแปแแแแแแแถแแแ",
- "ticketId": "แขแแแแแแแแแขแแแแแแแแถแแแแแปแแแแแแแขแแแแ
แแแแแแแพแแ",
- "close": "แแทแแแแแปแแแแ",
- "delete": "แแปแแแแแปแแแแ",
- "deleteNoTranscript": "แแปแแแแแปแแแแแแแแแแแแแถแแแถแแแแแแพแ transcriptแ",
- "reopen": "แแพแแแแแปแแแแกแพแแแทแแ",
- "claim": "แแแฝแแแแแปแแแแ",
- "claimUser": "แแแฝแแแแแปแแแแแแแแ
แฑแแแแแแถแแแแถแแแแแแแแแแ แแแแฝแแขแแแแ",
- "unclaim": "แแแแแแฝแแแแแปแแแแ",
- "pin": "แแถแแแแแแปแแแแแปแแแแ",
- "unpin": "แแแแแแปแแแแแปแแแแ",
-
- "move": "แแแแถแแแแแแผแแแแแปแแแแ",
- "moveId": "แขแแแแแแแแแขแแแแแแแแถแแแแแแพแแแแแขแแแแ
แแแแแแถแแแแแแผแแแ
แ",
- "rename": "แแแแผแแแแแแแแแแปแแแแ",
- "renameName": "แแแแแแแแแธแแแแแถแแแแแแปแแแแแแแ",
- "add": "แแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแปแแแแ",
- "addUser": "แขแแแแแแแพแแแแถแแแแแแแแแผแแแแแแแแ",
- "remove": "แแแขแแแแแแแพแแแแถแแแ
แแแแธแแแแปแแแแ",
- "removeUser": "แขแแแแแแแพแแแแถแแแแแแแแแผแแแแ",
-
- "blacklist": "แแแแแแแแแแแแแแธแแแแ
แแแแปแแแแ",
- "blacklistView": "แแพแแแแแแธแแแแแธแแแแ
แแ
แแ
แปแแแแแแแ",
- "blacklistAdd": "แแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแแธแแแแ
แ",
- "blacklistRemove": "แแแขแแแแแแแพแแแแถแแแ
แแแแธแแแแแธแแแแ
แ",
- "blacklistGet": "แแแฝแแแถแแแแแแแถแแแแแขแทแแแธแขแแแแแแแพแแแแถแแแแแแปแแแแแแธแแแแ
แ",
- "blacklistGetUser": "แขแแแแแแแพแแแแถแแแแแแแแแผแแแแฝแแแแแแแถแแแแแขแทแแ",
- "stats": "แแพแแแแแทแแทแแธแแผแ, แแแถแแทแ แฌแแแแปแแแแ",
- "statsReset": "แแแแแแแแแทแแทแแผแแแถแแแขแแแกแพแแแทแ (แ
แถแแแแแแพแแแถแแแแธแแผแแแ)แ",
- "statsGlobal": "แแพแแแแแทแแทแแแปแแ",
- "statsUser": "แแพแแแแแทแแทแแธแขแแแแแแแพแแแแถแแแแแแปแแแแถแแแธแแแแแแพแ",
- "statsUserUser": "แขแแแแแแแพแแแแถแแแแแแแแแผแแแพแแ",
- "statsTicket": "แแพแแแแแทแแทแแธแแแแปแแแแแแแปแแแแถแแแธแแแแแแพแ",
- "statsTicketTicket": "แแแแปแแแแแแแแแแผแแแพแแ",
-
- "clear": "แแปแแแแแปแแแแ
แแแพแแแแแปแแแแแแแแฝแแ",
- "clearFilter": "แแแแแแแแแแถแแแแถแแแแแขแถแแแแแปแแแแ",
- "clearFilters": {
- "all": "แแถแแแขแแ",
- "open": "แแพแ",
- "close": "แแทแ",
- "claim": "แแแฝแแ แพแ",
- "unclaim": "แแทแแแถแแแแแฝแ",
- "pin": "แแถแแแแแแปแแ แพแ",
- "unpin": "แแทแแแถแแแแถแแแแแแปแ",
- "autoclose": "แแทแแแแแแแแแแแแแแแแแท"
- },
-
- "autoclose": "แแแแแแแแแ autoclose แแแแปแแแแแปแแแแ",
- "autocloseDisable": "แแทแ autoclose แแแแปแแแแแปแแแแแแแ",
- "autocloseEnable": "แแพแ autoclose แแแแปแแแแแปแแแแแแแ",
- "autocloseEnableTime": "แ
แแแฝแแแแแแแแแแแแปแแแแแแแแแแผแแแทแแแแแแ แแพแแแแธแแทแแ",
- "autodelete": "แแแแแแแแแ autodelete แแแแปแแแแแปแแแแ",
- "autodeleteDisable": "แแทแ autodelete แแแแปแแแแแปแแแแแแแ",
- "autodeleteEnable": "แแพแ autodelete แแแแปแแแแแปแแแแแแแ",
- "autodeleteEnableTime": "แ
แแแฝแแแแแแแแแแแแปแแแแแแแแแแผแแแทแแแแแแ แแพแแแแธแแปแแ",
-
- "topic": "แแแแแแแแแแแแแแถแแแแแแแแถแแแแแปแแแแ",
- "topicSet": "แแแแแแแแแแถแแแแแแแแถแแแแแปแแแแ",
- "topicValue": "แแแแแถแแแแแแแธแแแแแแแแแถแแ",
- "topicList": "แแแฝแแแถแแแแแแธแแแแปแแแแแถแแแขแแ แแถแแฝแแแแแแถแแแ แแทแแแแแทแแทแ",
- "priority": "แแแแแแแแแแขแถแแทแแถแแแแแปแแแแ",
- "prioritySet": "แแแแแแขแถแแทแแถแแแแแปแแแแ",
- "priorityValue": "แขแถแแทแแถแแแแแแแแแแถแแ",
- "priorityGet": "แแแฝแแแถแแขแถแแทแแถแแแแแปแแแแ",
- "priorityList": "แแแฝแแแถแแแแแแธแแแแปแแแแแถแแแขแแ แแถแแฝแแแแแถแแแถแแขแถแแทแแถแแ",
- "transfer": "แแแแแแแถแแแถแแแ
แถแแแแแแปแแแแแธแขแแแแแแแพแแแแถแแแแแแถแแแแ
แแแแถแแแแแแ",
- "transferUser": "แขแแแแแแแพแแแแถแแแแแแแแแผแแแแแแแแ
แ"
- },
- "helpMenu": {
- "help": "แแแฝแแแถแแแแแแธแแถแแแแแแแแถแแแแแถแแ",
- "ticket": "แแแแแพแแแแแปแแแแแแแถแแแ",
- "close": "แแทแแแแแปแแแ, แแทแแธแแแแแทแแแถแแแแแแแแแแปแแแแแแถแแ",
- "delete": "แแปแแแแแปแแแ, แแทแแธแแแแแแแแพแ transcript แแ
แแแแแพแแ",
- "reopen": "แแพแแแแแปแแแแกแพแแแทแ, แแทแแธแแแแแพแแแถแแแแแแแแแแปแแแแแแถแแแแแแแแแ",
- "pin": "แแถแแแแแแปแแแแแปแแแแ แแถแแนแแแแแถแแแแแแปแแแแแ
แแถแแแพ แ แพแแแแแแแ '๐' แแ
แแแแแแ",
- "unpin": "แแแแแแปแแแแแปแแแแ แแแแปแแแแแนแแแ
แแแแแแแแแ แแแปแแแแแแนแแแถแแ '๐'แ",
- "move": "แแแแถแแแแแแผแแแแแปแแแแ แแถแแนแแแแแผแแแแแแแแแแแแแแแปแแแแ",
- "rename": "แแแแผแแแแแแแแแแปแแแแ แแถแแนแแแแแผแแแแแแแแแแแถแแแแแแแแแปแแแแ",
- "claim": "แแแฝแแแแแปแแแแ แแแแแทแแธแแแ แขแแแแขแถแ
แแแแถแแแแแแปแแแแแแขแแแแแถแขแแแแแแแปแแแแแแแแถแแแแแปแแแแแแแ",
- "unclaim": "แแแแแแฝแแแแแปแแแแ แแแแแทแแธแแแ แขแแแแขแถแ
แแแแถแแแแแแปแแแแแแขแแแแแถแแแแปแแแแแแแแแแแแ",
- "add": "แแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแปแแแแ แแถแแนแแขแแปแแแแถแแฑแแแขแแแแแแแพแแแแถแแแขแถแแแทแแแแแแแแแแปแแแแแปแแแแ",
- "remove": "แแแขแแแแแแแพแแแแถแแแ
แแแแธแแแแปแแแแ แแถแแนแแแแแทแแแแทแขแถแแแทแแแแแแแแแแแขแแแแแแแพแแแแถแแแแแแปแแแแแปแแแแ",
- "panel": "แแแแ แถแแแถแแแถแแฝแ dropdown แฌ buttons (แแแแแถแแแแถแแแแแแพแแแแแปแแแ)แ",
- "blacklistView": "แแพแแแแแแธแแแแแธแแแแ
แแ
แแ
แปแแแแแแแ",
- "blacklistAdd": "แแแแแแแขแแแแแแแพแแแแถแแแแ
แแแแแธแแแแ
แ",
- "blacklistRemove": "แแแขแแแแแแแพแแแแถแแแ
แแแแธแแแแแธแแแแ
แ",
- "blacklistGet": "แแแฝแแแถแแแแแแแถแแแแแขแทแแแธแขแแแแแแแพแแแแถแแแแแแปแแแแแแธแแแแ
แ",
- "statsGlobal": "แแพแแแแแทแแทแแแปแแ",
- "statsTicket": "แแพแแแแแทแแทแแธแแแแปแแแแแแแปแแแแถแแแธแแแแแแพแ",
- "statsUser": "แแพแแแแแทแแทแแธแขแแแแแแแพแแแแถแแแแแแปแแแแถแแแธแแแแแแพแ",
- "statsReset": "แแแแแแแแแทแแทแแผแแแถแแแขแแแกแพแแแทแ (แ
แถแแแแแแพแแแถแแแแธแแผแแแ)แ",
- "autocloseDisable": "แแทแ autoclose แแแแปแแแแแปแแแแแแแ",
- "autocloseEnable": "แแพแ autoclose แแแแปแแแแแปแแแแแแแ",
- "autodeleteDisable": "แแทแ autodelete แแแแปแแแแแปแแแแแแแ",
- "autodeleteEnable": "แแพแ autodelete แแแแปแแแแแปแแแแแแแ",
- "categories": {
- "general": "แแถแแแแแแแแถแแผแแ
",
- "basicTicket": "แแถแแแแแแแแถแแแแปแแแแแผแแแแแถแ",
- "advancedTicket": "แแถแแแแแแแแถแแแแปแแแแแแแแทแแแแแแ",
- "userTicket": "แแถแแแแแแแแถแแแแปแแแแขแแแแแแแพแแแแถแแ",
- "admin": "แแถแแแแแแแแถ Admin",
- "advanced": "แแถแแแแแแแแถแแแแแทแแแแแแ",
- "extra": "แแถแแแแแแแแถแแแแแแ"
- }
- },
- "stats": {
- "scopes": {
- "global": "แแแแทแแทแแแปแ",
- "system": "แแแแทแแทแแแแแแแแ",
- "user": "แแแแทแแทแขแแแแแแแพแแแแถแแ",
- "ticket": "แแแแทแแทแแแแปแแแ",
- "participants": "แขแแแแ
แผแแแฝแ",
- "messages": "แแถแ"
- },
- "properties": {
- "ticketsCreated": "แแแแปแแแแแถแแแแแแพแ",
- "ticketsClosed": "แแแแปแแแแแถแแแทแ",
- "ticketsDeleted": "แแแแปแแแแแถแแแปแ",
- "ticketsReopened": "แแแแปแแแแแถแแแพแแกแพแแแทแ",
- "ticketsAutoclosed": "แแแแปแแแแแถแแแทแแแแแแแแแแแแแแแแแท",
- "ticketsClaimed": "แแแแปแแแแแถแแแแฝแ",
- "ticketsPinned": "แแแแปแแแแแถแแแถแแแแแแปแ",
- "ticketsMoved": "แแแแปแแแแแถแแแแแถแแแแแแผแ",
- "usersBlacklisted": "แขแแแแแแแพแแแแถแแแแแแปแแแแแแธแแแแ
",
- "transcriptsCreated": "Transcript แแถแแแแแแพแ",
- "ticketsAutodeleted": "แแแแปแแแแแถแแแปแแแแแแแแแแแแแแแแแท",
- "ticketsTransferred": "แแแแปแแแแแถแแแแแแ",
- "ticketVolume": "แ
แแแฝแแแแแปแแแ",
- "averageTickets": "แ
แแแฝแแแแแปแแแแแถแแแแแ/แขแแแแแแแพ",
- "currentTickets": "แแแแปแแแแแ
แแ
แปแแแแแแ",
- "age": "แขแถแแปแแแแปแแแ",
- "responseTime": "แแแแแแแพแแแ",
- "resolutionTime": "แแแแแแแแแแถแ",
- "createdOn": "แแแแแพแแแ
",
- "createdBy": "แแแแแพแแแแ",
- "closedOn": "แแทแแแ
",
- "closedBy": "แแทแแแแ",
- "claimedOn": "แแแฝแแแ
",
- "claimedBy": "แแแฝแแแแ",
- "pinnedOn": "แแถแแแแแแปแแแ
",
- "pinnedBy": "แแถแแแแแแปแแแแ",
- "deletedOn": "แแปแแแ
",
- "deletedBy": "แแปแแแแ"
- },
- "roles": {
- "developer": "Developer",
- "serverOwner": "แแแ
แถแแแแแถแแแธแแแแแแพ",
- "serverAdmin": "Admin แแแถแแแธแแแแแแพ",
- "moderator": "แแแแปแแขแแแแแแแแปแแแแแแฝแ",
- "support": "แแแแปแแแแแฝแ",
- "member": "แแแถแแทแ"
- }
- },
- "panel": {
- "selectTicket": "แแแแพแแแพแแแแแปแแแแแแแแขแแแ",
- "selectRole": "แแแแพแแแพแแแฝแแถแแธแแแแแขแแแ",
- "selectOption": "แแแแพแแแพแแแแแแพแแแแแแขแแแ"
- },
- "priorities": {
- "urgent": "แแแแแถแแแแแแถแแ",
- "veryHigh": "แแแแแแแถแแ",
- "high": "แแแแแ",
- "normal": "แแแแแแถ",
- "low": "แแถแ",
- "veryLow": "แแถแแแถแแ",
- "none": "แแแแถแ"
- }
-}
+}
\ No newline at end of file
diff --git a/languages/korean.json b/languages/korean.json
index 00e2d6b..17234c6 100644
--- a/languages/korean.json
+++ b/languages/korean.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Korean",
diff --git a/languages/kurdish.json b/languages/kurdish.json
index 0b14b78..be9547e 100644
--- a/languages/kurdish.json
+++ b/languages/kurdish.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Kurdish",
diff --git a/languages/latvian.json b/languages/latvian.json
index 859e8ce..16755a1 100644
--- a/languages/latvian.json
+++ b/languages/latvian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["NoOneNook"],
"lastedited":"16/02/2026",
"language":"Latvian",
diff --git a/languages/lithuanian.json b/languages/lithuanian.json
index ba21919..9c32861 100644
--- a/languages/lithuanian.json
+++ b/languages/lithuanian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["TsgIndrius"],
"lastedited":"16/02/2026",
"language":"Lithuanian",
diff --git a/languages/norwegian.json b/languages/norwegian.json
index 42b6ff5..a87a119 100644
--- a/languages/norwegian.json
+++ b/languages/norwegian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["NoOneNook"],
"lastedited":"16/02/2026",
"language":"Norwegian",
diff --git a/languages/persian.json b/languages/persian.json
index f262ff9..2d79b24 100644
--- a/languages/persian.json
+++ b/languages/persian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["dysashop","zhavis"],
"lastedited":"16/02/2026",
"language":"Persian",
diff --git a/languages/polish.json b/languages/polish.json
index ae3bcc9..b30c1c0 100644
--- a/languages/polish.json
+++ b/languages/polish.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["DanoGlez"],
"lastedited":"16/02/2026",
"language":"Polish",
diff --git a/languages/portuguese.json b/languages/portuguese.json
index 182a73d..3e3ad64 100644
--- a/languages/portuguese.json
+++ b/languages/portuguese.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["quiradon"],
"lastedited":"16/02/2026",
"language":"Portuguese",
diff --git a/languages/romanian.json b/languages/romanian.json
index 36e26ee..3521dc7 100644
--- a/languages/romanian.json
+++ b/languages/romanian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["SankeDev"],
"lastedited":"16/02/2026",
"language":"Romanian",
diff --git a/languages/russian.json b/languages/russian.json
index adc1081..16e833c 100644
--- a/languages/russian.json
+++ b/languages/russian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["NoOneNook"],
"lastedited":"16/02/2026",
"language":"Russian",
diff --git a/languages/simplified-chinese.json b/languages/simplified-chinese.json
index 07457d7..4d1564c 100644
--- a/languages/simplified-chinese.json
+++ b/languages/simplified-chinese.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Simplified Chainese",
diff --git a/languages/slovenian.json b/languages/slovenian.json
index 6ec6988..305d3e4 100644
--- a/languages/slovenian.json
+++ b/languages/slovenian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Solvenian",
diff --git a/languages/spanish.json b/languages/spanish.json
index f9d7335..cf15d56 100644
--- a/languages/spanish.json
+++ b/languages/spanish.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["Redactado","Josuens"],
"lastedited":"16/02/2026",
"language":"Spanish",
diff --git a/languages/swedish.json b/languages/swedish.json
index d71f506..15571cc 100644
--- a/languages/swedish.json
+++ b/languages/swedish.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["NoOneNook"],
"lastedited":"16/02/2026",
"language":"Svenska",
diff --git a/languages/tamil.json b/languages/tamil.json
index 0a52857..9b68dc7 100644
--- a/languages/tamil.json
+++ b/languages/tamil.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["HanumeshGupta","ChatGPT"],
"lastedited":"16/02/2026",
"language":"Tamil",
diff --git a/languages/thai.json b/languages/thai.json
index 71f1294..f2b4b6a 100644
--- a/languages/thai.json
+++ b/languages/thai.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["modshd"],
"lastedited":"16/02/2026",
"language":"Thai",
diff --git a/languages/traditional-chinese.json b/languages/traditional-chinese.json
new file mode 100644
index 0000000..d44f21c
--- /dev/null
+++ b/languages/traditional-chinese.json
@@ -0,0 +1,608 @@
+{
+ "_TRANSLATION":{
+ "otversion":"v4.2.0",
+ "translators":["me.october"],
+ "lastedited":"10/03/2026",
+ "language":"Traditional Chinese",
+ "automated":false
+ },
+ "checker":{
+ "system":{
+ "typeError":"[้ฏ่ชค]",
+ "headerOpenTicket":"้ๅๅทฅๅฎ",
+ "typeWarning":"[่ญฆๅ]",
+ "typeInfo":"[ไฟกๆฏ]",
+ "headerConfigChecker":"้
็ฝฎๆชขๆฅๅจ",
+ "headerDescription":"ๆชขๆฅๆจ็้
็ฝฎๆไปถไธญ็้ฏ่ชค๏ผ",
+ "footerError":"ๆฉๅจไบบๅฐ็กๆณๅๅ๏ผ็ดๅฐๆๆ{0}้ฏ่ชค่ขซไฟฎ่ค๏ผ",
+ "footerWarning":"ๅปบ่ญฐๅจๅๅๅไฟฎ่คๆๆ{0}่ญฆๅ๏ผ",
+ "footerSupport":"ๆฏๆด๏ผ{0} - ๆๆช๏ผ{1}",
+ "compactInformation":"ไฝฟ็จ{0}็ฒๅๆดๅคไฟกๆฏ๏ผ",
+ "dataPath":"่ทฏๅพ",
+ "dataDocs":"ๆๆช",
+ "dataMessages":"ๆถๆฏ"
+ },
+ "messages":{
+ "stringTooShort":"ๆญคๅญ็ฌฆไธฒไธ่ฝๅฐๆผ{0}ๅๅญ็ฌฆ๏ผ",
+ "stringTooLong":"ๆญคๅญ็ฌฆไธฒไธ่ฝ่ถ
้{0}ๅๅญ็ฌฆ๏ผ",
+ "stringLengthInvalid":"ๆญคๅญ็ฌฆไธฒ้ทๅบฆๅฟ
้ ็บ{0}ๅๅญ็ฌฆ๏ผ",
+ "stringStartsWith":"ๆญคๅญ็ฌฆไธฒๅฟ
้ ไปฅ{0}้้ ญ๏ผ",
+ "stringEndsWith":"ๆญคๅญ็ฌฆไธฒๅฟ
้ ไปฅ{0}็ตๅฐพ๏ผ",
+ "stringContains":"ๆญคๅญ็ฌฆไธฒๅฟ
้ ๅ
ๅซ{0}๏ผ",
+ "stringChoices":"ๆญคๅญ็ฌฆไธฒ้ป่ฝๆฏไปฅไธๅผไนไธ๏ผ{0}๏ผ",
+ "stringRegex":"ๆญคๅญ็ฌฆไธฒ็กๆ๏ผ",
+ "stringInvertedContains":"ๆญคๅญ็ฌฆไธฒไธ่ฝๅ
ๅซ {0}๏ผ",
+ "stringLowercase":"ๆญคๅญ็ฌฆไธฒๅฟ
้ ๅ
จ้จไฝฟ็จๅฐๅฏซๅญๆฏ๏ผ",
+ "stringUppercase":"ๆญคๅญ็ฌฆไธฒๅฟ
้ ๅ
จ้จไฝฟ็จๅคงๅฏซๅญๆฏ๏ผ",
+ "stringSpecialCharacters":"ๆญคๅญ็ฌฆไธฒไธ่ฝๅ
ๅซไปปไฝ็นๆฎๅญ็ฌฆ๏ผ๏ผๅ
ๅ
่จฑ a-zใ0-9 ๅ็ฉบๆ ผ๏ผ",
+ "stringNoSpaces":"ๆญคๅญ็ฌฆไธฒไธ่ฝๅ
ๅซ็ฉบๆ ผ๏ผ",
+ "stringCapitalWord":"ๅปบ่ญฐๆญคๅญ็ฌฆไธฒไธญ็ๆฏๅๅฎ่ฉ้ฝไปฅๅคงๅฏซๅญๆฏ้้ ญ๏ผ",
+ "stringCapitalSentence":"ๆญคๅญ็ฌฆไธฒไธญ็ๆไบๅฅๅญไผผไนๅๆไปฅๅคงๅฏซๅญๆฏ้้ ญ๏ผ",
+ "stringPunctuation":"ๆญคๅญ็ฌฆไธฒไธญ็ๅฅๅญไผผไนๅๆไปฅๆจ้ป็ฌฆ่็ตๅฐพ๏ผ",
+
+ "numberTooShort":"ๆญคๆธๅญไธ่ฝๅฐๆผ{0}ไฝ๏ผ",
+ "numberTooLong":"ๆญคๆธๅญไธ่ฝ่ถ
้{0}ไฝ๏ผ",
+ "numberLengthInvalid":"ๆญคๆธๅญ้ทๅบฆๅฟ
้ ็บ{0}ไฝ๏ผ",
+ "numberTooSmall":"ๆญคๆธๅญ่ณๅฐ็บ{0}๏ผ",
+ "numberTooLarge":"ๆญคๆธๅญๆๅค็บ{0}๏ผ",
+ "numberNotEqual":"ๆญคๆธๅญๅฟ
้ ็บ{0}๏ผ",
+ "numberStep":"ๆญคๆธๅญๅฟ
้ ๆฏ{0}็ๅๆธ๏ผ",
+ "numberStepOffset":"ๆญคๆธๅญๅฟ
้ ๆฏ{0}็ๅๆธ๏ผ่ตทๅงๅผ็บ{1}๏ผ",
+ "numberStartsWith":"ๆญคๆธๅญๅฟ
้ ไปฅ{0}้้ ญ๏ผ",
+ "numberEndsWith":"ๆญคๆธๅญๅฟ
้ ไปฅ{0}็ตๅฐพ๏ผ",
+ "numberContains":"ๆญคๆธๅญๅฟ
้ ๅ
ๅซ{0}๏ผ",
+ "numberChoices":"ๆญคๆธๅญ้ป่ฝๆฏไปฅไธๅผไนไธ๏ผ{0}๏ผ",
+ "numberFloat":"ๆญคๆธๅญไธ่ฝ็บๅฐๆธ๏ผ",
+ "numberNegative":"ๆญคๆธๅญไธ่ฝ็บ่ฒ ๆธ๏ผ",
+ "numberPositive":"ๆญคๆธๅญไธ่ฝ็บๆญฃๆธ๏ผ",
+ "numberZero":"ๆญคๆธๅญไธ่ฝ็บ้ถ๏ผ",
+ "numberNan":"ๆญคๆธๅญไธ่ฝ็บ NaN๏ผ้ๆธๅญ๏ผ๏ผ",
+ "numberInvertedContains":"ๆญคๆธๅญไธ่ฝๅ
ๅซ {0}๏ผ",
+
+ "booleanTrue":"ๆญคไฝ็พๅผไธ่ฝ็บ็๏ผ",
+ "booleanFalse":"ๆญคไฝ็พๅผไธ่ฝ็บๅ๏ผ",
+
+ "arrayEmptyDisabled":"ๆญคๆธ็ตไธๅ
่จฑ็บ็ฉบ๏ผ",
+ "arrayEmptyRequired":"ๆญคๆธ็ตๅฟ
้ ็บ็ฉบ๏ผ",
+ "arrayTooShort":"ๆญคๆธ็ต้ทๅบฆ่ณๅฐ็บ{0}๏ผ",
+ "arrayTooLong":"ๆญคๆธ็ต้ทๅบฆๆๅค็บ{0}๏ผ",
+ "arrayLengthInvalid":"ๆญคๆธ็ต้ทๅบฆๅฟ
้ ็บ{0}๏ผ",
+ "arrayInvalidTypes":"ๆญคๆธ็ต้ป่ฝๅ
ๅซไปฅไธ้กๅ๏ผ{0}๏ผ",
+ "arrayDouble":"ๆญคๆธ็ตไธๅ
่จฑ้่คๅผ๏ผ",
+
+ "discordInvalidId":"้ๆฏ็กๆ็Discord {0} ID๏ผ",
+ "discordInvalidIdOptions":"้ๆฏ็กๆ็Discord {0} ID๏ผๆจ้ๅฏไปฅไฝฟ็จไปฅไธไนไธ๏ผ{1}๏ผ",
+ "discordInvalidToken":"้ๆฏ็กๆ็Discordไปค็๏ผๆๆณไธ๏ผ๏ผ",
+ "colorInvalid":"้ๆฏ็กๆ็ๅๅ
ญ้ฒ่ฃฝ้ก่ฒ๏ผ",
+ "emojiTooShort":"ๆญคๅญ็ฌฆไธฒ่ณๅฐ้่ฆ{0}ๅ้ถๆ
็ฌฆ่๏ผ",
+ "emojiTooLong":"ๆญคๅญ็ฌฆไธฒๆๅค้ป่ฝๆ{0}ๅ้ถๆ
็ฌฆ่๏ผ",
+ "emojiCustom":"ๆญค้ถๆ
็ฌฆ่ไธ่ฝๆฏ่ชๅฎ็พฉDiscord้ถๆ
็ฌฆ่๏ผ",
+ "emojiInvalid":"้ๆฏ็กๆ็้ถๆ
็ฌฆ่๏ผ",
+ "urlInvalid":"ๆญคURL็กๆ๏ผ",
+ "urlInvalidHttp":"This url can only use the https:// protocol!",
+ "urlInvalidProtocol":"This url can only use the http:// & https:// protocols!",
+ "urlInvalidHostname":"ๆญคURL็ไธปๆฉๅไธ่ขซๅ
่จฑ๏ผ",
+ "urlInvalidExtension":"ๆญคURL็ๆดๅฑๅ็กๆ๏ผ่ซ้ธๆ๏ผ{0}๏ผ",
+ "urlInvalidPath":"ๆญคURL็่ทฏๅพ็กๆ๏ผ",
+ "idNotUnique":"ๆญคIDไธๅฏไธ๏ผ่ซไฝฟ็จๅ
ถไปID๏ผ",
+ "idNonExistent":"ID {0}ไธๅญๅจ๏ผ",
+
+ "invalidType":"ๆญคๅฑฌๆงๅฟ
้ ็บ้กๅ๏ผ{0}๏ผ",
+ "propertyMissing":"ๆญคๅฐ่ฑก็ผบๅฐๅฑฌๆง{0}๏ผ",
+ "propertyOptional":"ๆญคๅฐ่ฑกไธญ็ๅฑฌๆง{0}ๆฏๅฏ้ธ็๏ผ",
+ "objectDisabled":"ๆญคๅฐ่ฑกๅทฒ็ฆ็จ๏ผ่ซไฝฟ็จ{0}ๅ็จ๏ผ",
+ "nullInvalid":"ๆญคๅฑฌๆงไธ่ฝ็บnull๏ผ",
+ "switchInvalidType":"ๆญคๅฑฌๆงๅฟ
้ ๆฏไปฅไธ้กๅไนไธ๏ผ{0}๏ผ",
+ "objectSwitchInvalid":"ๆญคๅฐ่ฑกๅฟ
้ ๆฏไปฅไธ้กๅไนไธ๏ผ{0}๏ผ",
+
+ "invalidLanguage":"้ๆฏ็กๆ็่ช่จ๏ผ",
+ "invalidButton":"ๆญคๆ้ๅฟ
้ ่ณๅฐๆไธๅ{0}ๆ{1}๏ผ",
+ "unusedOption":"้ธ้
{0}ๆชๅจไปปไฝๅฐๆนไฝฟ็จ๏ผ",
+ "unusedQuestion":"ๅ้ก{0}ๆชๅจไปปไฝๅฐๆนไฝฟ็จ๏ผ",
+ "dropdownOption":"ๅ็จไธๆ่ๅฎ็้บต้้ป่ฝๅ
ๅซโticketโ้กๅ็้ธ้
๏ผ",
+ "customInvalidVersion":"้
็ฝฎๆไปถไธญๆๅฎ็็ๆฌไธๅน้
๏ผ่ซ็ขบไฟๆจๅทฒๅฐ้
็ฝฎๆดๆฐ่ณๆๆฐ็ๆฌ๏ผ"
+ }
+ },
+ "actions":{
+ "buttons":{
+ "create":"่จชๅๅทฅๅฎ",
+ "close":"้้ๅทฅๅฎ",
+ "delete":"ๅช้คๅทฅๅฎ",
+ "reopen":"้ๆฐ้ๅๅทฅๅฎ",
+ "claim":"่ช้ ๅทฅๅฎ",
+ "unclaim":"ๅๆถ่ช้ ๅทฅๅฎ",
+ "pin":"็ฝฎ้ ๅทฅๅฎ",
+ "unpin":"ๅๆถ็ฝฎ้ ๅทฅๅฎ",
+ "clear":"ๅช้คๅทฅๅฎ",
+ "helpSwitchSlash":"ๆชข่ฆๆๆ ๅฝไปค",
+ "helpSwitchText":"ๆชข่ฆๆๆฌๅฝไปค",
+ "helpPage":"็ฌฌ{0}้ ",
+ "withReason":"ๅธถๅๅ ",
+ "withoutTranscript":"ไธๅธถ่จ้"
+ },
+ "titles":{
+ "created":"ๅทฅๅฎๅทฒๅตๅปบ",
+ "close":"ๅทฅๅฎๅทฒ้้",
+ "delete":"ๅทฅๅฎๅทฒๅช้ค",
+ "reopen":"ๅทฅๅฎๅทฒ้ๆฐ้ๅ",
+ "claim":"ๅทฅๅฎๅทฒ่ช้ ",
+ "unclaim":"ๅทฅๅฎๅทฒๅๆถ่ช้ ",
+ "pin":"ๅทฅๅฎๅทฒ็ฝฎ้ ",
+ "unpin":"ๅทฅๅฎๅทฒๅๆถ็ฝฎ้ ",
+ "rename":"ๅทฅๅฎๅทฒ้ๅฝๅ",
+ "move":"ๅทฅๅฎๅทฒ็งปๅ",
+ "add":"ๅทฅๅฎ็จๆถๅทฒๆทปๅ ",
+ "remove":"ๅทฅๅฎ็จๆถๅทฒ็งป้ค",
+
+ "help":"ๅฏ็จๅฝไปค",
+ "statsReset":"้็ฝฎ็ตฑ่จ",
+ "blacklistAdd":"็จๆถๅทฒๆ้ป",
+ "blacklistRemove":"็จๆถๅทฒ่งฃ็ฆ",
+ "blacklistGet":"ๅทฒๆ้ป็จๆถ",
+ "blacklistView":"็ถๅ้ปๅๅฎ",
+ "blacklistAddDm":"ๅทฒๅ ๅ
ฅ้ปๅๅฎ",
+ "blacklistRemoveDm":"ๅทฒๅพ้ปๅๅฎ็งป้ค",
+ "clear":"ๅทฅๅฎๅทฒๆธ
้ค",
+ "clearTickets":"ๆธ
้คๅทฅๅฎ",
+ "roles":"่ง่ฒๅทฒๆดๆฐ",
+
+ "autoclose":"ๅทฅๅฎ่ชๅ้้",
+ "autocloseEnabled":"่ชๅ้้ๅทฒๅ็จ",
+ "autocloseDisabled":"่ชๅ้้ๅทฒ็ฆ็จ",
+ "autodelete":"ๅทฅๅฎ่ชๅๅช้ค",
+ "autodeleteEnabled":"่ชๅๅช้คๅทฒๅ็จ",
+ "autodeleteDisabled":"่ชๅๅช้คๅทฒ็ฆ็จ",
+
+ "topicSet":"ไธป้กๅทฒๆดๆน",
+ "prioritySet":"ๅชๅ
็ดๅทฒๆดๆน",
+ "priorityGet":"ๅทฅๅฎๅชๅ
็ด",
+ "transfer":"ๅทฅๅฎๅทฒ่ฝ็งป"
+ },
+ "descriptions":{
+ "create":"ๆจ็ๅทฅๅฎๅทฒๅตๅปบใ้ป้ธไธๆนๆ้่จชๅ๏ผ",
+ "close":"ๅทฅๅฎๅทฒๆๅ้้๏ผ",
+ "delete":"ๅทฅๅฎๅทฒๆๅๅช้ค๏ผ",
+ "reopen":"ๅทฅๅฎๅทฒๆๅ้ๆฐ้ๅ๏ผ",
+ "claim":"ๅทฅๅฎๅทฒๆๅ่ช้ ๏ผ",
+ "unclaim":"ๅทฅๅฎๅทฒๆๅๅๆถ่ช้ ๏ผ",
+ "pin":"ๅทฅๅฎๅทฒๆๅ็ฝฎ้ ๏ผ",
+ "unpin":"ๅทฅๅฎๅทฒๆๅๅๆถ็ฝฎ้ ๏ผ",
+ "rename":"ๅทฅๅฎๅทฒๆๅ้ๅฝๅ็บ{0}๏ผ",
+ "move":"ๅทฅๅฎๅทฒๆๅ็งปๅๅฐ{0}๏ผ",
+ "add":"{0}ๅทฒๆๅๆทปๅ ๅฐๅทฅๅฎ๏ผ",
+ "remove":"{0}ๅทฒๆๅๅพๅทฅๅฎ็งป้ค๏ผ",
+
+ "helpExplanation":"`<ๅ็จฑ>` => ๅฟ
ๅกซๅๆธ\n`[ๅ็จฑ]` => ๅฏ้ธๅๆธ",
+ "statsReset":"ๆฉๅจไบบ็ตฑ่จๅทฒๆๅ้็ฝฎ๏ผ",
+ "statsError":"็กๆณๆชข่ฆๅทฅๅฎ็ตฑ่จ๏ผ\n{0}ไธๆฏๅทฅๅฎ๏ผ",
+ "blacklistAdd":"{0}ๅทฒๆๅๆ้ป๏ผ",
+ "blacklistRemove":"{0}ๅทฒๆๅ่งฃ็ฆ๏ผ",
+ "blacklistGetSuccess":"{0}็ถๅๅทฒ่ขซๆ้ป๏ผ",
+ "blacklistGetEmpty":"{0}็ถๅๆช่ขซๆ้ป๏ผ",
+ "blacklistViewEmpty":"ๅฐๆชๆไบบ่ขซๆ้ป๏ผ",
+ "blacklistViewTip":"ไฝฟ็จโ/blacklist addโๆ้ป็จๆถ๏ผ",
+ "clearVerify":"็ขบๅฎ่ฆๅช้คๅคๅๅทฅๅฎๅ๏ผ\nๆญคๆไฝ็กๆณๆค้ท๏ผ",
+ "clearReady":"{0}ๅๅทฅๅฎๅทฒๆๅๅช้ค๏ผ",
+ "rolesEmpty":"ๆชๆดๆฐไปปไฝ่ง่ฒ๏ผ",
+
+ "autocloseLeave":"ๆญคๅทฅๅฎๅทฒ่ชๅ้้๏ผๅ ็บๅตๅปบ่
้ข้ไบๆๅๅจ๏ผ",
+ "autocloseTimeout":"ๆญคๅทฅๅฎๅทฒ่ชๅ้้๏ผๅ ็บๅฎๅทฒ่ถ
้`{0}ๅฐๆ`ๆชๆดปๅ๏ผ",
+ "autodeleteLeave":"ๆญคๅทฅๅฎๅทฒ่ชๅๅช้ค๏ผๅ ็บๅตๅปบ่
้ข้ไบๆๅๅจ๏ผ",
+ "autodeleteTimeout":"ๆญคๅทฅๅฎๅทฒ่ชๅๅช้ค๏ผๅ ็บๅฎๅทฒ่ถ
้`{0}ๅคฉ`ๆชๆดปๅ๏ผ",
+ "autocloseEnabled":"ๆญคๅทฅๅฎๅทฒๅ็จ่ชๅ้้๏ผ\n่ถ
้`{0}ๅฐๆ`ๆชๆดปๅๅพๅฐ่ชๅ้้๏ผ",
+ "autocloseDisabled":"ๆญคๅทฅๅฎๅทฒ็ฆ็จ่ชๅ้้๏ผ\nไธๅ่ชๅ้้๏ผ",
+ "autodeleteEnabled":"ๆญคๅทฅๅฎๅทฒๅ็จ่ชๅๅช้ค๏ผ\n่ถ
้`{0}ๅคฉ`ๆชๆดปๅๅพๅฐ่ชๅๅช้ค๏ผ",
+ "autodeleteDisabled":"ๆญคๅทฅๅฎๅทฒ็ฆ็จ่ชๅๅช้ค๏ผ\nไธๅ่ชๅๅช้ค๏ผ",
+
+ "ticketMessageLimit":"ๆจ้ป่ฝๅๆๅตๅปบ{0}ๅๅทฅๅฎ๏ผ",
+ "ticketMessageAutoclose":"ๆญคๅทฅๅฎๅฐๅจ่ถ
้{0}ๅฐๆๆชๆดปๅๅพ่ชๅ้้๏ผ",
+ "ticketMessageAutodelete":"ๆญคๅทฅๅฎๅฐๅจ่ถ
้{0}ๅคฉๆชๆดปๅๅพ่ชๅๅช้ค๏ผ",
+ "panelReady":"้บต้ๅทฒๅจๅพ็บๆถๆฏไธญๅฏ็จ๏ผ\nๆญคๆถๆฏ็พๅจๅฏไปฅๅช้ค๏ผ",
+
+ "topicSet":"้ ป้ไธป้กๅทฒ็ฑ {0} ๆๅๆดๆน๏ผ",
+ "prioritySet":"ๅทฅๅฎๅชๅ
็ดๅทฒ็ฑ {1} ๆๅๆดๆน็บ {0}๏ผ",
+ "priorityGet":"ๆญคๅทฅๅฎ็ถๅ็ๅชๅ
็ด็บ {0}ใ",
+ "transfer":"ๅทฅๅฎๆๆๆฌๅทฒ็ฑ {2} ๆๅๅพ {0} ่ฝ็งป่ณ {1}๏ผ"
+ },
+ "modal":{
+ "closePlaceholder":"ๆจ็บไป้บผ้้ๆญคๅทฅๅฎ๏ผ",
+ "deletePlaceholder":"ๆจ็บไป้บผๅช้คๆญคๅทฅๅฎ๏ผ",
+ "reopenPlaceholder":"ๆจ็บไป้บผ้ๆฐ้ๅๆญคๅทฅๅฎ๏ผ",
+ "claimPlaceholder":"ๆจ็บไป้บผ่ช้ ๆญคๅทฅๅฎ๏ผ",
+ "unclaimPlaceholder":"ๆจ็บไป้บผๅๆถ่ช้ ๆญคๅทฅๅฎ๏ผ",
+ "pinPlaceholder":"ๆจ็บไป้บผ็ฝฎ้ ๆญคๅทฅๅฎ๏ผ",
+ "unpinPlaceholder":"ๆจ็บไป้บผๅๆถ็ฝฎ้ ๆญคๅทฅๅฎ๏ผ"
+ },
+ "logs":{
+ "createLog":"{0}ๅตๅปบไบไธๅๆฐๅทฅๅฎ๏ผ",
+ "closeLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{0}้้๏ผ",
+ "closeDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญ้้๏ผ",
+ "deleteLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{0}ๅช้ค๏ผ",
+ "deleteDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญๅช้ค๏ผ",
+ "reopenLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{0}้ๆฐ้ๅ๏ผ",
+ "reopenDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญ้ๆฐ้ๅ๏ผ",
+ "claimLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{0}่ช้ ๏ผ",
+ "claimDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญ่ขซ่ช้ ๏ผ",
+ "unclaimLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{0}ๅๆถ่ช้ ๏ผ",
+ "unclaimDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญๅๆถ่ช้ ๏ผ",
+ "pinLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{0}็ฝฎ้ ๏ผ",
+ "pinDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญ็ฝฎ้ ๏ผ",
+ "unpinLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{0}ๅๆถ็ฝฎ้ ๏ผ",
+ "unpinDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญๅๆถ็ฝฎ้ ๏ผ",
+ "renameLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{1}้ๅฝๅ็บ{0}๏ผ",
+ "renameDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญ้ๅฝๅ็บ{0}๏ผ",
+ "moveLog":"ๆญคๅทฅๅฎๅทฒ่ขซ{1}็งปๅๅฐ{0}๏ผ",
+ "moveDm":"ๆจ็ๅทฅๅฎๅทฒๅจๆๅ็ๆๅๅจไธญ็งปๅๅฐ{0}๏ผ",
+ "addLog":"{0}ๅทฒ่ขซ{1}ๆทปๅ ๅฐๆญคๅทฅๅฎ๏ผ",
+ "addDm":"{0}ๅทฒ่ขซๆทปๅ ๅฐๆจ็ๅทฅๅฎไธญ๏ผ",
+ "removeLog":"{0}ๅทฒ่ขซ{1}ๅพๆญคๅทฅๅฎ็งป้ค๏ผ",
+ "removeDm":"{0}ๅทฒ่ขซๅพๆจ็ๅทฅๅฎไธญ็งป้ค๏ผ",
+
+ "blacklistAddLog":"{0}่ขซ{1}ๆ้ป๏ผ",
+ "blacklistRemoveLog":"{0}่ขซ{1}ๅพ้ปๅๅฎ็งป้ค๏ผ",
+ "blacklistAddDm":"ๆจๅทฒ่ขซๆๅ็ๆๅๅจๆ้ป๏ผ\nๅพ็พๅจ่ตท๏ผๆจ็กๆณๅตๅปบๅทฅๅฎ๏ผ",
+ "blacklistRemoveDm":"ๆจๅทฒ่ขซๆๅ็ๆๅๅจ่งฃ็ฆ๏ผ\n็พๅจๆจๅฏไปฅๅๆฌกๅตๅปบๅทฅๅฎ๏ผ",
+ "clearLog":"{0}ๅๅทฅๅฎๅทฒ่ขซ{1}ๅช้ค๏ผ",
+
+ "transferLog":"ๆญคๅทฅๅฎ็ๆๆๆฌๅทฒ็ฑ {2} ๅพ {0} ่ฝ็งป่ณ {1}๏ผ",
+ "transferDm":"ๆจๅจๆๅๅจไธญ็ๅทฅๅฎๆๆๆฌๅทฒๅพ {0} ่ฝ็งป่ณ {1}๏ผ",
+ "prioritySetLog":"ๆญคๅทฅๅฎ็ๅชๅ
็ดๅทฒ็ฑ {1} ๆดๆน็บ {0}๏ผ",
+ "prioritySetDm":"ๆจๅจๆๅๅจไธญ็ๅทฅๅฎๅชๅ
็ดๅทฒๆดๆน็บ {0}๏ผ",
+ "roleUpdateLog":"{0} ๅทฒๆดๆฐๅ
ถ่ง่ฒ๏ผ",
+ "roleUpdateDm":"ๆจๅจๆๅๅจไธญ็่ง่ฒๅทฒๆดๆฐ๏ผ"
+ }
+ },
+ "transcripts":{
+ "success":{
+ "visit":"ๆชข่ฆ่จ้",
+ "ready":"่จ้ๅทฒๅตๅปบ",
+ "textFileDescription":"้ๆฏๅทฒๅช้คๅทฅๅฎ็ๆๆฌ่จ้๏ผ",
+ "htmlProgress":"่ซ็ญๅพ
ๆญคHTML่จ้่็ๅฎๆ...",
+
+ "createdChannel":"ๆๅๅจไธญๅทฒๅตๅปบไธๅๆฐ็{0}่จ้๏ผ",
+ "createdCreator":"ๅทฒ็บๆจ็ๅทฅๅฎๅตๅปบไธๅๆฐ็{0}่จ้๏ผ",
+ "createdParticipant":"ๆจๅ่็ๅทฅๅฎไธญๅทฒๅตๅปบไธๅๆฐ็{0}่จ้๏ผ",
+ "createdActiveAdmin":"ๆจไฝ็บ็ฎก็ๅกๅ่็ๅทฅๅฎไธญๅทฒๅตๅปบไธๅๆฐ็{0}่จ้๏ผ",
+ "createdEveryAdmin":"ๆจๆพๆไปป็ฎก็ๅก็ๅทฅๅฎไธญๅทฒๅตๅปบไธๅๆฐ็{0}่จ้๏ผ",
+ "createdOther":"ๅทฒๅตๅปบไธๅๆฐ็{0}่จ้๏ผ"
+ },
+ "errors":{
+ "retry":"้่ฉฆ",
+ "continue":"ๅช้ค็ก่จ้",
+ "backup":"ๅตๅปบๅไปฝ่จ้",
+ "error":"ๅตๅปบ่จ้ๆๅบ้ฏใ\nๆจๆณๆ้บผๅ๏ผ\n\nๅจๆจ้ป้ธไปฅไธๆ้ไนๅ๏ผๆญคๅทฅๅฎไธๆ่ขซๅช้คใ",
+ "title":"่จ้้ฏ่ชค"
+ },
+ "text":{
+ "messagesTitle":"ๆถๆฏ",
+ "embedTitle":"EMBED",
+ "fileTitle":"ๆไปถ",
+ "fieldsTitle":"ๅญๆฎต",
+ "reactionsTitle":"ๅๆ",
+ "statsTitle":"็ตฑ่จ",
+ "emptyContent":"<ๅ
งๅฎน็บ็ฉบ>",
+ "noTitle":"<็กๆจ้ก>",
+ "noDesc":"<็กๆ่ฟฐ>"
+ }
+ },
+ "errors":{
+ "titles":{
+ "internalError":"ๅ
ง้จ้ฏ่ชค",
+ "optionMissing":"ๅฝไปค้ธ้
็ผบๅคฑ",
+ "optionInvalid":"ๅฝไปค้ธ้
็กๆ",
+ "unknownCommand":"ๆช็ฅๅฝไปค",
+ "noPermissions":"็กๆฌ้",
+ "unknownTicket":"ๆช็ฅๅทฅๅฎ",
+ "deprecatedTicket":"้ๆๅทฅๅฎ",
+ "unknownOption":"ๆช็ฅ้ธ้
",
+ "unknownPanel":"ๆช็ฅ้บต้",
+ "notInGuild":"ไธๅจๆๅๅจไธญ",
+ "channelRename":"็กๆณ้ๅฝๅ้ ป้",
+ "busy":"ๅทฅๅฎ็นๅฟ",
+ "permissionError":"ๆฌ้้ฏ่ชค"
+ },
+ "descriptions":{
+ "askForInfo":"่ซ่ฏไฟๆญคๆฉๅจไบบ็ๆๆ่
็ฒๅๆดๅคไฟกๆฏ๏ผ",
+ "askForInfoResolve":"ๅฆๆๆญคๅ้กๅจๅคๆฌกๅ่ฉฆๅพไปๆช่งฃๆฑบ๏ผ่ซ่ฏไฟๆญคๆฉๅจไบบ็ๆๆ่
ใ",
+ "internalError":"็ฑๆผๅ
ง้จ้ฏ่ชค๏ผ็กๆณๅ้ฟๆญค{0}๏ผ",
+ "optionMissing":"ๆญคๅฝไปค็ผบๅฐๅฟ
ๅกซๅๆธ๏ผ",
+ "optionInvalid":"ๆญคๅฝไปคไธญ็ๅๆธ็กๆ๏ผ",
+ "optionInvalidChoose":"่ซ้ธๆ",
+ "unknownCommand":"่ซ่จชๅๅนซๅฉ่ๅฎ็ฒๅๆดๅคไฟกๆฏ๏ผ",
+ "noPermissions":"ๆจ็กๆฌไฝฟ็จๆญค{0}๏ผ",
+ "noPermissionsList":"ๆ้ๆฌ้๏ผ๏ผๅ
ถไธญไนไธ๏ผ",
+ "noPermissionsCooldown":"ๆจๅ ๅทๅปๆ้็กๆณไฝฟ็จๆญค{0}๏ผ",
+ "noPermissionsBlacklist":"ๆจๅ ่ขซๆ้ป็กๆณไฝฟ็จๆญค{0}๏ผ",
+ "noPermissionsLimitGlobal":"ๆจ็กๆณๅตๅปบๅทฅๅฎ๏ผๅ ็บๆๅๅจๅทฒ้ๅฐๆๅคงๅทฅๅฎ้่ฃฝ๏ผ",
+ "noPermissionsLimitGlobalUser":"ๆจ็กๆณๅตๅปบๅทฅๅฎ๏ผๅ ็บๆจๅทฒ้ๅฐๆๅคงๅทฅๅฎ้่ฃฝ๏ผ",
+ "noPermissionsLimitOption":"ๆจ็กๆณๅตๅปบๅทฅๅฎ๏ผๅ ็บๆๅๅจๅทฒ้ๅฐๆญค้ธ้
็ๆๅคงๅทฅๅฎ้่ฃฝ๏ผ",
+ "noPermissionsLimitOptionUser":"ๆจ็กๆณๅตๅปบๅทฅๅฎ๏ผๅ ็บๆจๅทฒ้ๅฐๆญค้ธ้
็ๆๅคงๅทฅๅฎ้่ฃฝ๏ผ",
+ "unknownTicket":"่ซๅจๆๆๅทฅๅฎไธญ้่ฉฆๆญคๅฝไปค๏ผ",
+ "deprecatedTicket":"็ถๅ้ ป้ไธๆฏๆๆๅทฅๅฎ๏ผๅฏ่ฝๆฏ่็Open Ticket็ๅทฅๅฎ๏ผ",
+ "notInGuild":"ๆญค{0}ๅจ็งไฟกไธญ็กๆ๏ผ่ซๅจๆๅๅจไธญ้่ฉฆ๏ผ",
+ "channelRename":"็ฑๆผDiscord้็้่ฃฝ๏ผๆฉๅจไบบ็ฎๅ็กๆณ้ๅฝๅ้ ป้ใๅฆๆๆฉๅจไบบๆช้ๅ๏ผ้ ป้ๅฐๅจ10ๅ้พๅพ่ชๅ้ๅฝๅใ",
+ "channelRenameSource":"ๆญค้ฏ่ชค็ไพๆบๆฏ๏ผ{0}",
+ "busy":"็กๆณไฝฟ็จๆญค{0}๏ผ\nๅทฅๅฎ็ถๅๆญฃๅจ่ขซๆฉๅจไบบ่็ใ\n\n่ซๅนพ็งๅพ้่ฉฆ๏ผ",
+ "closeBeforeMessage":"็จๆถ็ผ้ๆถๆฏไนๅ๏ผ็กๆณ้้ๆๅช้คๆญคๅทฅๅฎใ",
+ "closeBeforeAdminMessage":"ๅทฅๅฎ็ฎก็ๅกๆๆฏๆดๆๅก็ผ้ๆถๆฏไนๅ๏ผ็กๆณ้้ๆๅช้คๆญคๅทฅๅฎใ",
+ "unableToCreateTicket":"ๆจ็กๆณๅตๅปบๅทฅๅฎใ"
+ },
+ "optionInvalidReasons":{
+ "stringRegex":"ๅผไธ็ฌฆๅๆจกๅผ๏ผ",
+ "stringMinLength":"ๅผ่ณๅฐ้่ฆ{0}ๅๅญ็ฌฆ๏ผ",
+ "stringMaxLength":"ๅผๆๅค้่ฆ{0}ๅๅญ็ฌฆ๏ผ",
+ "numberInvalid":"็กๆๆธๅญ๏ผ",
+ "numberMin":"ๆธๅญ่ณๅฐ็บ{0}๏ผ",
+ "numberMax":"ๆธๅญๆๅค็บ{0}๏ผ",
+ "numberDecimal":"ๆธๅญไธ่ฝ็บๅฐๆธ๏ผ",
+ "numberNegative":"ๆธๅญไธ่ฝ็บ่ฒ ๆธ๏ผ",
+ "numberPositive":"ๆธๅญไธ่ฝ็บๆญฃๆธ๏ผ",
+ "numberZero":"ๆธๅญไธ่ฝ็บ้ถ๏ผ",
+ "channelNotFound":"็กๆณๆพๅฐ้ ป้๏ผ",
+ "userNotFound":"็กๆณๆพๅฐ็จๆถ๏ผ",
+ "roleNotFound":"็กๆณๆพๅฐ่ง่ฒ๏ผ",
+ "memberNotFound":"็กๆณๆพๅฐ็จๆถ๏ผ",
+ "mentionableNotFound":"็กๆณๆพๅฐ็จๆถๆ่ง่ฒ๏ผ",
+ "channelType":"็กๆ็้ ป้้กๅ๏ผ",
+ "notInGuild":"ๆญค้ธ้
้่ฆๆจๅจๆๅๅจไธญ๏ผ"
+ },
+ "permissions":{
+ "developer":"ๆจ้่ฆๆฏๆฉๅจไบบ็้็ผ่
ใ",
+ "owner":"ๆจ้่ฆๆฏๆๅๅจๆๆ่
ใ",
+ "admin":"ๆจ้่ฆๆฏๆๅๅจ็ฎก็ๅกใ",
+ "moderator":"ๆจ้่ฆๆฏ็ไธปใ",
+ "support":"ๆจ้่ฆๆฏๆฏๆดๅ้ๆๅกใ",
+ "member":"ๆจ้่ฆๆฏๆๅกใ",
+ "discord-administrator":"ๆจ้่ฆๆๆ`ADMINISTRATOR`ๆฌ้ใ"
+ },
+ "actionInvalid":{
+ "close":"ๅทฅๅฎๅทฒ้้๏ผ",
+ "reopen":"ๅทฅๅฎๆช้้๏ผ",
+ "claim":"ๅทฅๅฎๅทฒ่ช้ ๏ผ",
+ "unclaim":"ๅทฅๅฎๆช่ช้ ๏ผ",
+ "pin":"ๅทฅๅฎๅทฒ็ฝฎ้ ๏ผ",
+ "unpin":"ๅทฅๅฎๆช็ฝฎ้ ๏ผ",
+ "add":"ๆญค็จๆถๅทฒๅฏ่จชๅๅทฅๅฎ๏ผ",
+ "remove":"็กๆณๅพๆญคๅทฅๅฎ็งป้คๆญค็จๆถ๏ผ"
+ }
+ },
+ "params":{
+ "uppercase":{
+ "ticket":"ๅทฅๅฎ",
+ "tickets":"ๅทฅๅฎ",
+ "reason":"ๅๅ ",
+ "creator":"ๅตๅปบ่
",
+ "remaining":"ๅฉ้คๆ้",
+ "added":"ๅทฒๆทปๅ ",
+ "removed":"ๅทฒ็งป้ค",
+ "filter":"็ฏฉ้ธ",
+ "method":"ๆนๅผ",
+ "type":"้กๅ",
+ "blacklisted":"ๅทฒๆ้ป",
+ "panel":"้บต้",
+ "command":"ๅฝไปค",
+ "system":"ไฟ็ตฑ",
+ "true":"ๆฏ",
+ "false":"ๅฆ",
+ "syntax":"ๆๆณ",
+ "originalName":"ๅๅ็จฑ",
+ "newName":"ๆฐๅ็จฑ",
+ "until":"็ดๅฐ",
+ "validOptions":"ๆๆ้ธ้
",
+ "validPanels":"ๆๆ้บต้",
+ "autoclose":"่ชๅ้้",
+ "autodelete":"่ชๅๅช้ค",
+ "startupDate":"ๅๅๆฅๆ",
+ "version":"็ๆฌ",
+ "name":"ๅ็จฑ",
+ "role":"่ง่ฒ",
+ "status":"็ๆ
",
+ "claimed":"ๅทฒ่ช้ ",
+ "pinned":"ๅทฒ็ฝฎ้ ",
+ "creationDate":"ๅตๅปบๆฅๆ",
+
+ "noone":"็กไบบ",
+ "open":"้ๅ",
+ "closed":"้้",
+ "priority":"ๅชๅ
็ด",
+ "participants":"ๅ่่
",
+ "yes":"ๆฏ",
+ "no":"ๅฆ",
+ "option":"้ธ้
",
+ "topic":"ไธป้ก",
+ "uptime":"ไฟ็ตฑ้่กๆ้",
+ "messages":"ๆถๆฏ",
+ "embeds":"ๅตๅ
ฅ",
+ "files":"ๆไปถ",
+ "components":"็ตไปถ",
+ "cooldown":"ๅทๅปๆ้",
+ "maxTickets":"ๆๅคงๅทฅๅฎๆธ",
+ "admins":"็ฎก็ๅก",
+ "roles":"่ง่ฒ",
+ "size":"ๅคงๅฐ"
+ },
+ "lowercase":{
+ "text":"ๆๆฌ",
+ "html":"HTML",
+ "command":"ๅฝไปค",
+ "modal":"ๆจกๆ
ๆก",
+ "button":"ๆ้",
+ "dropdown":"ไธๆ่ๅฎ",
+ "method":"ๆนๅผ"
+ }
+ },
+ "commands":{
+ "reason":"ๆๅฎไธๅๅฏ้ธๅๅ ๏ผ่ฉฒๅๅ ๅฐๅจๆฅ่ชไธญๅฏ่ฆใ",
+ "help":"็ฒๅๆๆๅฏ็จๅฝไปค็ๅ้ถใ",
+ "panel":"็ๆๅธถๆไธๆ่ๅฎๆๆ้็ๆถๆฏ๏ผ็จๆผๅทฅๅฎๅตๅปบ๏ผใ",
+ "panelId":"ๆจๆณ่ฆ็ๆ็้บต้็ๆจ่ญ็ฌฆใ",
+ "panelAutoUpdate":"ๆจๅธๆๆญค้บต้ๅจ็ทจ่ผฏๆ่ชๅๆดๆฐๅ๏ผ",
+ "ticket":"็ซๅณๅตๅปบไธๅๅทฅๅฎใ",
+ "ticketId":"ๆจๆณ่ฆๅตๅปบ็ๅทฅๅฎ็ๆจ่ญ็ฌฆใ",
+ "close":"้้ไธๅๅทฅๅฎใ",
+ "delete":"ๅช้คไธๅๅทฅๅฎใ",
+ "deleteNoTranscript":"ๅช้คๆญคๅทฅๅฎ่ไธๅตๅปบ่จ้ใ",
+ "reopen":"้ๆฐ้ๅไธๅๅทฅๅฎใ",
+ "claim":"่ช้ ไธๅๅทฅๅฎใ",
+ "claimUser":"ๅฐๆญคๅทฅๅฎ่ช้ ็ตฆๅ
ถไปไบบ่ไธๆฏๆจ่ชๅทฑใ",
+ "unclaim":"ๅๆถ่ช้ ไธๅๅทฅๅฎใ",
+ "pin":"็ฝฎ้ ไธๅๅทฅๅฎใ",
+ "unpin":"ๅๆถ็ฝฎ้ ไธๅๅทฅๅฎใ",
+
+ "move":"็งปๅไธๅๅทฅๅฎใ",
+ "moveId":"ๆจๆณ่ฆ็งปๅๅฐ็้ธ้
็ๆจ่ญ็ฌฆใ",
+ "rename":"้ๅฝๅไธๅๅทฅๅฎใ",
+ "renameName":"ๆญคๅทฅๅฎ็ๆฐๅ็จฑใ",
+ "add":"ๅฐ็จๆถๆทปๅ ๅฐๅทฅๅฎใ",
+ "addUser":"่ฆๆทปๅ ็็จๆถใ",
+ "remove":"ๅพๅทฅๅฎไธญ็งป้ค็จๆถใ",
+ "removeUser":"่ฆ็งป้ค็็จๆถใ",
+
+ "blacklist":"็ฎก็ๅทฅๅฎ้ปๅๅฎใ",
+ "blacklistView":"ๆชข่ฆ็ถๅ้ปๅๅฎ็ๅ้ถใ",
+ "blacklistAdd":"ๅฐ็จๆถๆทปๅ ๅฐ้ปๅๅฎใ",
+ "blacklistRemove":"ๅพ้ปๅๅฎไธญ็งป้ค็จๆถใ",
+ "blacklistGet":"็ฒๅ่ขซๆ้ป็จๆถ็่ฉณ็ดฐไฟกๆฏใ",
+ "blacklistGetUser":"่ฆ็ฒๅ่ฉณ็ดฐไฟกๆฏ็็จๆถใ",
+ "stats":"ๆชข่ฆๆฉๅจไบบใๆๅกๆๅทฅๅฎ็็ตฑ่จไฟกๆฏใ",
+ "statsReset":"้็ฝฎๆฉๅจไบบ็ๆๆ็ตฑ่จไฟกๆฏ๏ผไธฆๅพ้ถ้ๅง่จๆธ๏ผใ",
+ "statsGlobal":"ๆชข่ฆๅ
จๅฑ็ตฑ่จไฟกๆฏใ",
+ "statsUser":"ๆชข่ฆๆๅๅจไธญ็จๆถ็็ตฑ่จไฟกๆฏใ",
+ "statsUserUser":"่ฆๆชข่ฆ็็จๆถใ",
+ "statsTicket":"ๆชข่ฆๆๅๅจไธญๅทฅๅฎ็็ตฑ่จไฟกๆฏใ",
+ "statsTicketTicket":"่ฆๆชข่ฆ็ๅทฅๅฎใ",
+
+ "clear":"ๅๆๅช้คๅคๅๅทฅๅฎใ",
+ "clearFilter":"ๆธ
้คๅทฅๅฎ็็ฏฉ้ธๆขไปถใ",
+ "clearFilters":{
+ "all":"ๅ
จ้จ",
+ "open":"้ๅ",
+ "close":"้้",
+ "claim":"ๅทฒ่ช้ ",
+ "unclaim":"ๆช่ช้ ",
+ "pin":"ๅทฒ็ฝฎ้ ",
+ "unpin":"ๆช็ฝฎ้ ",
+ "autoclose":"่ชๅ้้"
+ },
+
+ "autoclose":"็ฎก็ๅทฅๅฎไธญ็่ชๅ้้ใ",
+ "autocloseDisable":"็ฆ็จๆญคๅทฅๅฎ็่ชๅ้้ใ",
+ "autocloseEnable":"ๅ็จๆญคๅทฅๅฎ็่ชๅ้้ใ",
+ "autocloseEnableTime":"ๅทฅๅฎ้่ฆๅคๅฐๅฐๆไธๆดปๅๆ่ฝ่ชๅ้้ใ",
+ "autodelete":"็ฎก็ๅทฅๅฎไธญ็่ชๅๅช้คใ",
+ "autodeleteDisable":"็ฆ็จๆญคๅทฅๅฎ็่ชๅๅช้คใ",
+ "autodeleteEnable":"ๅ็จๆญคๅทฅๅฎ็่ชๅๅช้คใ",
+ "autodeleteEnableTime":"ๅทฅๅฎ้่ฆๅคๅฐๅคฉไธๆดปๅๆ่ฝ่ชๅๅช้คใ",
+
+ "topic":"็ฎก็ๅทฅๅฎ้ ป้็ไธป้กใ",
+ "topicSet":"่จญๅฎๅทฅๅฎ้ ป้็ไธป้กใ",
+ "topicValue":"้ ป้็ๆฐไธป้กใ",
+ "topicList":"็ฒๅๆๆๅทฅๅฎๅๅ
ถไธป้กๅ็ตฑ่จไฟกๆฏ็ๅ้ถใ",
+ "priority":"็ฎก็ๅทฅๅฎ็ๅชๅ
็ดใ",
+ "prioritySet":"่จญๅฎๅทฅๅฎ็ๅชๅ
็ดใ",
+ "priorityValue":"้ ป้็ๅชๅ
็ดใ",
+ "priorityGet":"็ฒๅๅทฅๅฎ็ๅชๅ
็ดใ",
+ "priorityList":"็ฒๅๆๆๅทฅๅฎ็ๅชๅ
็ด็ๆ
ๅ้ถใ",
+ "transfer":"ๅฐๅทฅๅฎๆๆๆฌๅพไธไฝ็จๆถ่ฝ็งป่ณๅฆไธไฝ็จๆถใ",
+ "transferUser":"่ฆ่ฝ็งป็ตฆ็็จๆถใ"
+ },
+ "helpMenu":{
+ "help":"็ฒๅๆๆๅฏ็จๅฝไปค็ๅ้ถใ",
+ "ticket":"็ซๅณๅตๅปบไธๅๅทฅๅฎใ",
+ "close":"้้ไธๅๅทฅๅฎ๏ผ้ๅฐ็ฆ็จๆญค้ ป้็ๅฏซๅ
ฅๆฌ้ใ",
+ "delete":"ๅช้คไธๅๅทฅๅฎ๏ผๅ็จๆๆๅตๅปบ่จ้ใ",
+ "reopen":"้ๆฐ้ๅไธๅๅทฅๅฎ๏ผ้ๅฐ้ๆฐๅ็จๆญค้ ป้็ๅฏซๅ
ฅๆฌ้ใ",
+ "pin":"็ฝฎ้ ไธๅๅทฅๅฎใ้ๅฐๆๅทฅๅฎ็งปๅๅฐ้ ้จ๏ผไธฆๅจๅ็จฑๅๆทปๅ '๐'้ถๆ
็ฌฆ่ใ",
+ "unpin":"ๅๆถ็ฝฎ้ ไธๅๅทฅๅฎใๅทฅๅฎๅฐไฟๆ็ถๅไฝ็ฝฎ๏ผไฝๆ็งป้ค'๐'้ถๆ
็ฌฆ่ใ",
+ "move":"็งปๅไธๅๅทฅๅฎใ้ๅฐๆดๆนๆญคๅทฅๅฎ็้กๅใ",
+ "rename":"้ๅฝๅไธๅๅทฅๅฎใ้ๅฐๆดๆนๆญคๅทฅๅฎ็้ ป้ๅ็จฑใ",
+ "claim":"่ช้ ไธๅๅทฅๅฎใ้้ๆญคๆไฝ๏ผๆจๅฏไปฅๅ็ฅๅ้ๆจๆญฃๅจ่็ๆญคๅทฅๅฎใ",
+ "unclaim":"ๅๆถ่ช้ ไธๅๅทฅๅฎใ้้ๆญคๆไฝ๏ผๆจๅฏไปฅๅ็ฅๅ้ๆญคๅทฅๅฎๅทฒ็ฉบ้ใ",
+ "add":"ๅฐ็จๆถๆทปๅ ๅฐๅทฅๅฎใ้ๅฐๅ
่จฑ็จๆถๅจๆญคๅทฅๅฎไธญ่ฎๅๅๅฏซๅ
ฅใ",
+ "remove":"ๅพๅทฅๅฎไธญ็งป้ค็จๆถใ้ๅฐ็งป้ค็จๆถๅจๆญคๅทฅๅฎไธญ่ฎๅๅๅฏซๅ
ฅ็ๆฌ้ใ",
+ "panel":"็ๆๅธถๆไธๆ่ๅฎๆๆ้็ๆถๆฏ๏ผ็จๆผๅทฅๅฎๅตๅปบ๏ผใ",
+ "blacklistView":"ๆชข่ฆ็ถๅ้ปๅๅฎ็ๅ้ถใ",
+ "blacklistAdd":"ๅฐ็จๆถๆทปๅ ๅฐ้ปๅๅฎใ",
+ "blacklistRemove":"ๅพ้ปๅๅฎไธญ็งป้ค็จๆถใ",
+ "blacklistGet":"็ฒๅ่ขซๆ้ป็จๆถ็่ฉณ็ดฐไฟกๆฏใ",
+ "statsGlobal":"ๆชข่ฆๅ
จๅฑ็ตฑ่จไฟกๆฏใ",
+ "statsTicket":"ๆชข่ฆๆๅๅจไธญๅทฅๅฎ็็ตฑ่จไฟกๆฏใ",
+ "statsUser":"ๆชข่ฆๆๅๅจไธญ็จๆถ็็ตฑ่จไฟกๆฏใ",
+ "statsReset":"้็ฝฎๆฉๅจไบบ็ๆๆ็ตฑ่จไฟกๆฏ๏ผไธฆๅพ้ถ้ๅง่จๆธ๏ผใ",
+ "autocloseDisable":"็ฆ็จๆญคๅทฅๅฎ็่ชๅ้้ใ",
+ "autocloseEnable":"ๅ็จๆญคๅทฅๅฎ็่ชๅ้้ใ",
+ "autodeleteDisable":"็ฆ็จๆญคๅทฅๅฎ็่ชๅๅช้คใ",
+ "autodeleteEnable":"ๅ็จๆญคๅทฅๅฎ็่ชๅๅช้คใ",
+ "categories":{
+ "general":"้็จๅฝไปค",
+ "basicTicket":"ๅบ็คๅทฅๅฎๅฝไปค",
+ "advancedTicket":"้ซ็ดๅทฅๅฎๅฝไปค",
+ "userTicket":"็จๆถๅทฅๅฎๅฝไปค",
+ "admin":"็ฎก็ๅกๅฝไปค",
+ "advanced":"้ซ็ดๅฝไปค",
+ "extra":"้กๅคๅฝไปค"
+ }
+ },
+ "stats":{
+ "scopes":{
+ "global":"ๅ
จๅฑ็ตฑ่จ",
+ "system":"ไฟ็ตฑ็ตฑ่จ",
+ "user":"็จๆถ็ตฑ่จ",
+ "ticket":"ๅทฅๅฎ็ตฑ่จ",
+ "participants":"ๅ่่
",
+ "messages":"ๆถๆฏ"
+ },
+ "properties":{
+ "ticketsCreated":"ๅทฅๅฎๅทฒๅตๅปบ",
+ "ticketsClosed":"ๅทฅๅฎๅทฒ้้",
+ "ticketsDeleted":"ๅทฅๅฎๅทฒๅช้ค",
+ "ticketsReopened":"ๅทฅๅฎๅทฒ้ๆฐ้ๅ",
+ "ticketsAutoclosed":"ๅทฅๅฎๅทฒ่ชๅ้้",
+ "ticketsClaimed":"ๅทฅๅฎๅทฒ่ช้ ",
+ "ticketsPinned":"ๅทฅๅฎๅทฒ็ฝฎ้ ",
+ "ticketsMoved":"ๅทฅๅฎๅทฒ็งปๅ",
+ "usersBlacklisted":"็จๆถๅทฒๆ้ป",
+ "transcriptsCreated":"่จ้ๅทฒๅตๅปบ",
+ "ticketsAutodeleted":"่ชๅๅช้ค็ๅทฅๅฎ",
+ "ticketsTransferred":"ๅทฒ่ฝ็งป็ๅทฅๅฎ",
+ "ticketVolume":"ๅทฅๅฎ้",
+ "averageTickets":"ๅนณๅๅทฅๅฎๆธ/็จๆถ",
+ "currentTickets":"็ถๅๅทฅๅฎ",
+ "age":"ๅทฅๅฎๆ้ท",
+ "responseTime":"ๅ้ฟๆ้",
+ "resolutionTime":"่งฃๆฑบๆ้",
+ "createdOn":"ๅตๅปบๆผ",
+ "createdBy":"ๅตๅปบ่
",
+ "closedOn":"้้ๆผ",
+ "closedBy":"้้่
",
+ "claimedOn":"่ช้ ๆผ",
+ "claimedBy":"่ช้ ่
",
+ "pinnedOn":"ๅบๅฎๆผ",
+ "pinnedBy":"ๅบๅฎ่
",
+ "deletedOn":"ๅช้คๆผ",
+ "deletedBy":"ๅช้ค่
"
+ },
+ "roles":{
+ "developer":"้็ผ่
",
+ "serverOwner":"ๆๅๅจๆๆ่
",
+ "serverAdmin":"ๆๅๅจ็ฎก็ๅก",
+ "moderator":"็ฎก็ๅ้",
+ "support":"ๆฏๆดๅ้",
+ "member":"ๆๅก"
+ }
+ },
+ "panel":{
+ "selectTicket":"้ธๆๆจ็ๅทฅๅฎ",
+ "selectRole":"้ธๆๆจ็่ง่ฒ",
+ "selectOption":"้ธๆๆจ็้ธ้
"
+ },
+ "priorities":{
+ "urgent":"็ทๆฅ",
+ "veryHigh":"้ๅธธ้ซ",
+ "high":"้ซ",
+ "normal":"ๆฎ้",
+ "low":"ไฝ",
+ "veryLow":"้ๅธธไฝ",
+ "none":"็ก"
+ }
+}
\ No newline at end of file
diff --git a/languages/turkish.json b/languages/turkish.json
index ee66fc5..09e949b 100644
--- a/languages/turkish.json
+++ b/languages/turkish.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["palestinian"],
"lastedited":"16/02/2026",
"language":"Turkish",
diff --git a/languages/ukrainian.json b/languages/ukrainian.json
index 416da30..c1c2a19 100644
--- a/languages/ukrainian.json
+++ b/languages/ukrainian.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["Anderskiy"],
"lastedited":"16/02/2026",
"language":"Ukrainian",
diff --git a/languages/vietnamese.json b/languages/vietnamese.json
index 12d6318..24f43c0 100644
--- a/languages/vietnamese.json
+++ b/languages/vietnamese.json
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
- "otversion":"v4.1.3",
+ "otversion":"v4.2.0",
"translators":["ngocdiep2006"],
"lastedited":"16/02/2026",
"language":"Vietnamese",
diff --git a/package.json b/package.json
index 087e7b3..92ca691 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "open-ticket",
"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! ",
"keywords": [
"ticket-bot",
@@ -19,20 +19,21 @@
"test": "node index.js --dev-config --dev-database --soft-plugins",
"testsetup": "node index.js --cli --dev-config --dev-database --soft-plugins",
"testnc": "node index.js --no-compile --dev-config --dev-database --soft-plugins",
- "docs": "npx typedoc --options .docs/typedoc-config.json && node .docs/createDocs.js",
- "mergelang": "node .docs/mergeTranslations.js"
+ "docs": "npx typedoc --options .tools/typedoc-config.json && node .tools/createDocs.js",
+ "mergelang": "node .tools/mergeTranslations.js"
},
- "type": "commonjs",
+ "type": "module",
"license": "GPL-3.0-only",
"dependencies": {
- "@discordjs/rest": "^2.6.0",
+ "@discordjs/rest": "^2.6.1",
+ "@open-discord-bots/framework": "^0.4.4",
"@types/node": "^22.5.0",
"@types/terminal-kit": "^2.5.7",
"ansis": "^4.2.0",
- "discord.js": "^14.24.2",
- "formatted-json-stringify": "^1.2.1",
+ "discord.js": "^14.26.4",
+ "formatted-json-stringify": "^1.3.2",
"terminal-kit": "^3.1.2",
- "typescript": "^5.9.3"
+ "typescript": "^6.0.3"
},
"repository": {
"type": "git",
@@ -45,7 +46,7 @@
"homepage": "https://openticket.dj-dj.be",
"imports": {
"#opendiscord": "./dist/src/index.js",
- "#opendiscord-types": "./dist/src/core/api/api.js"
+ "#opendiscord-types": "./dist/src/core/api.js"
},
"funding": {
"type": "individual",
diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts
index 5441b05..68b5b6a 100644
--- a/plugins/example-plugin/index.ts
+++ b/plugins/example-plugin/index.ts
@@ -6,15 +6,15 @@ import * as discord from "discord.js"
//// Enable it in the plugin.json file! ////
/////////////////////////////////////////////
-if (utilities.project != "openticket") throw new api.ODPluginError("This plugin only works in Open Ticket!")
+if (opendiscord.project != "openticket") throw new api.ODPluginError("This plugin only works in Open Ticket!")
//Add Typescript autocomplete support for plugin data. (!!!OPTIONAL!!!)
declare module "#opendiscord-types" {
- export interface ODPluginManagerIds_Default {
+ export interface ODPluginManagerIdMappings {
"example-plugin":api.ODPlugin
}
- export interface ODConfigManagerIds_Default {
- "example-plugin:config":api.ODJsonConfig
+ export interface ODConfigManagerIdMappings {
+ "example-plugin:config":api.ODJsonConfig<{testVariable1:boolean,testVariable2:number,testVariable3:string}>
}
}
@@ -30,7 +30,7 @@ opendiscord.events.get("onConfigLoad").listen((configManager) => {
//Let's also log it to the console to let us know it worked!
const ourConfig = configManager.get("example-plugin:config")
opendiscord.log("The example config loaded successfully!","plugin",[
- {key:"var-1",value:ourConfig.data.testVariable1},
+ {key:"var-1",value:ourConfig.data.testVariable1.toString()},
{key:"var-2",value:ourConfig.data.testVariable2.toString()},
{key:"var-3",value:ourConfig.data.testVariable3.toString()}
])
diff --git a/src/actions/addTicketUser.ts b/src/actions/addTicketUser.ts
index d595597..27da7ce 100644
--- a/src/actions/addTicketUser.ts
+++ b/src/actions/addTicketUser.ts
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET ADD USER SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:add-ticket-user"))
opendiscord.actions.get("opendiscord:add-ticket-user").workers.add([
- new api.ODWorker("opendiscord:add-ticket-user",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:add-ticket-user",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to add user to ticket! Open Ticket doesn't support threads!")
@@ -34,44 +34,31 @@ export const registerActions = async () => {
opendiscord.log("Failed to add channel permission overwrites on add-ticket-user","error")
}
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket user adding!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value,hidden:true}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(source,{guild,channel,user,ticket,reason,data})).message)
+ if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(origin,{guild,channel,user,ticket,reason,data})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketUserAdded").emit([ticket,user,data,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,data} = params
opendiscord.log(user.displayName+" added "+data.displayName+" to a ticket!","info",[
@@ -80,7 +67,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/actions/calculateTicketCategory.ts b/src/actions/calculateTicketCategory.ts
new file mode 100644
index 0000000..dcc2c49
--- /dev/null
+++ b/src/actions/calculateTicketCategory.ts
@@ -0,0 +1,129 @@
+///////////////////////////////////////
+//CALCULATE TICKET CATEGORY SYSTEM
+///////////////////////////////////////
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
+import * as discord from "discord.js"
+
+const generalConfig = opendiscord.configs.get("opendiscord:general")
+
+export async function registerActions(){
+ opendiscord.actions.add(new api.ODAction("opendiscord:calculate-ticket-category"))
+ opendiscord.actions.get("opendiscord:calculate-ticket-category").workers.add([
+ new api.ODWorker("opendiscord:default-category",2,async (instance,params,origin,cancel) => {
+ //handle default category
+ const {guild,user,channel,option,ticket,currentCategoryId} = params
+
+ const defaultCategoryId = option.get("opendiscord:channel-category").value
+ if (!defaultCategoryId){
+ //default category is disabled
+ instance.newCategoryId = null
+ instance.newCategoryMode = null
+ instance.newCategory = null
+ instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
+ }else{
+ const defaultCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,defaultCategoryId)
+ if (defaultCategory){
+ //default category is enabled
+ instance.newCategoryId = defaultCategoryId
+ instance.newCategoryMode = "default"
+ instance.newCategory = defaultCategory
+ instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
+ }else{
+ //default category is not found (do not switch categories)
+ opendiscord.log("Unable to find ticket category '"+defaultCategoryId+"' #1","error",[
+ {key:"categoryid",value:defaultCategoryId},
+ {key:"type",value:"default"}
+ ])
+ instance.newCategoryId = null
+ instance.newCategoryMode = null
+ instance.newCategory = null
+ instance.shouldChangeCategory = false
+ }
+ }
+ }),
+ new api.ODWorker("opendiscord:close-category",1,async (instance,params,origin,cancel) => {
+ //handle close category
+ const {guild,user,channel,option,ticket,currentCategoryId} = params
+ if (!ticket) return
+ if (!ticket.get("opendiscord:closed").value) return
+ if (!generalConfig.data.ticketSystem.closedCategory.enabled) return
+
+ const closeCategoryId = generalConfig.data.ticketSystem.closedCategory.categoryId
+ if (!closeCategoryId) return
+ const closeCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,closeCategoryId)
+ if (closeCategory){
+ //close category is enabled
+ instance.newCategoryId = closeCategoryId
+ instance.newCategoryMode = "close"
+ instance.newCategory = closeCategory
+ instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
+ }else{
+ //close category is not found (do not switch categories)
+ opendiscord.log("Unable to find ticket category '"+closeCategoryId+"' #2","error",[
+ {key:"categoryid",value:closeCategoryId},
+ {key:"type",value:"close"}
+ ])
+ instance.newCategoryId = null
+ instance.newCategoryMode = null
+ instance.newCategory = null
+ instance.shouldChangeCategory = false
+ }
+ }),
+ new api.ODWorker("opendiscord:claim-category",0,async (instance,params,origin,cancel) => {
+ //handle claim category
+ const {guild,user,channel,option,ticket,currentCategoryId} = params
+ if (!ticket) return
+ if (!ticket.get("opendiscord:claimed").value) return
+
+ const claimedCategoryIds = generalConfig.data.ticketSystem.claimedCategories
+ const claimCategoryId = claimedCategoryIds.find((c) => c.user == user.id)?.category
+ if (!claimCategoryId) return
+ const claimCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,claimCategoryId)
+ if (claimCategory){
+ //claim category is enabled
+ instance.newCategoryId = claimCategoryId
+ instance.newCategoryMode = "claim"
+ instance.newCategory = claimCategory
+ instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
+ }else{
+ //claim category is not found (do not switch categories)
+ opendiscord.log("Unable to find ticket category '"+claimCategoryId+"' #3","error",[
+ {key:"categoryid",value:claimCategoryId},
+ {key:"type",value:"claim"}
+ ])
+ instance.newCategoryId = null
+ instance.newCategoryMode = null
+ instance.newCategory = null
+ instance.shouldChangeCategory = false
+ }
+ }),
+ new api.ODWorker("opendiscord:backup-category",-100,async (instance,params,origin,cancel) => {
+ //handle backup category
+ const {guild,user,channel,option,ticket,currentCategoryId} = params
+ if (!instance.newCategory || !instance.newCategoryId || !instance.shouldChangeCategory) return
+ if (instance.newCategory.children.cache.size < 50) return
+ if (!generalConfig.data.ticketSystem.backupCategory.enabled) return
+
+ const backupCategoryId = generalConfig.data.ticketSystem.backupCategory.categoryId
+ if (!backupCategoryId) return
+ const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,backupCategoryId)
+ if (backupCategory){
+ //backup category is enabled
+ instance.newCategoryId = backupCategoryId
+ instance.newCategoryMode = "backup"
+ instance.newCategory = backupCategory
+ instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
+ }else{
+ //backup category is not found (do not switch categories)
+ opendiscord.log("Unable to find ticket category '"+backupCategoryId+"' #4","error",[
+ {key:"categoryid",value:backupCategoryId},
+ {key:"type",value:"backup"}
+ ])
+ instance.newCategoryId = null
+ instance.newCategoryMode = null
+ instance.newCategory = null
+ instance.shouldChangeCategory = false
+ }
+ })
+ ])
+}
\ No newline at end of file
diff --git a/src/actions/calculateTicketName.ts b/src/actions/calculateTicketName.ts
new file mode 100644
index 0000000..f6d1777
--- /dev/null
+++ b/src/actions/calculateTicketName.ts
@@ -0,0 +1,30 @@
+///////////////////////////////////////
+//CALCULATE TICKET NAME SYSTEM
+///////////////////////////////////////
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
+import * as discord from "discord.js"
+
+const generalConfig = opendiscord.configs.get("opendiscord:general")
+
+export async function registerActions(){
+ opendiscord.actions.add(new api.ODAction("opendiscord:calculate-ticket-name"))
+ opendiscord.actions.get("opendiscord:calculate-ticket-name").workers.add([
+ new api.ODWorker("opendiscord:calculate-ticket-name",0,async (instance,params,origin,cancel) => {
+ const {guild,user,channel,option,ticket,currentChannelName} = params
+
+ //calculate base channel name
+ const channelPrefix = option.get("opendiscord:channel-prefix").value
+ const channelSuffix = (ticket) ? ticket.get("opendiscord:channel-suffix").value : (await opendiscord.options.suffix.getSuffixFromOption(option,user,guild) ?? "unknown")
+ const channelRenamed = (ticket && ticket.exists("opendiscord:channel-renamed")) ? ticket.get("opendiscord:channel-renamed").value : null
+ const baseChannelName = (channelRenamed) ? channelRenamed : channelPrefix+channelSuffix
+
+ //calculate status emojis
+ const pinEmoji = (ticket && ticket.get("opendiscord:pinned").value) ? generalConfig.data.ticketSystem.pinEmoji : ""
+ const priorityEmoji = (ticket) ? (opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? "") : ""
+
+ instance.newChannelName = pinEmoji+priorityEmoji+baseChannelName
+ instance.newChannelSuffix = channelSuffix
+ instance.shouldChangeName = (instance.newChannelName !== currentChannelName)
+ })
+ ])
+}
\ No newline at end of file
diff --git a/src/actions/claimTicket.ts b/src/actions/claimTicket.ts
index 502db01..e6a8c79 100644
--- a/src/actions/claimTicket.ts
+++ b/src/actions/claimTicket.ts
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET CLAIMING SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:claim-ticket"))
opendiscord.actions.get("opendiscord:claim-ticket").workers.add([
- new api.ODWorker("opendiscord:claim-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:claim-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to claim ticket! Open Ticket doesn't support threads!")
@@ -22,67 +23,66 @@ export const registerActions = async () => {
ticket.get("opendiscord:busy").value = true
//update stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-claimed",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-claimed",user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-claimed",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-claimed",user.id,1,"increase")
- //update category
+ //calculate & update category
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
- const rawClaimCategory = ticket.option.get("opendiscord:channel-categories-claimed").value.find((c) => c.user == user.id)
- const claimCategory = (rawClaimCategory) ? rawClaimCategory.category : null
- if (claimCategory){
- try {
- channel.setParent(claimCategory,{lockPermissions:false})
- ticket.get("opendiscord:category-mode").value = "claimed"
- ticket.get("opendiscord:category").value = claimCategory
- }catch(e){
- opendiscord.log("Unable to move ticket to 'claimed category'!","error",[
+ const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("claim-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
+ if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
+ const originalCategoryName = channel.parent?.name ?? ""
+ const newCategoryName = categoryResult.newCategory?.name ?? ""
+ try{
+ await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
+ process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
+ })
+ ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
+ ticket.get("opendiscord:category").value = categoryResult.newCategoryId
+ }catch(err){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-claim",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
+ opendiscord.log("Unable to move ticket to claimed category.","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
- {key:"categoryid",value:claimCategory}
+ {key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
}
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket claiming!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(source,{guild,channel,user,ticket,reason})).message)
+ if (params.sendMessage){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(origin,{guild,channel,user,ticket,reason})).message)
+ if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
+ messageType:"claim-message",
+ messageOrigin:"other",
+ messageAuthor:user.id,
+ messageReason:reason
+ },false)
+ }
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketClaimed").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" claimed a ticket!","info",[
@@ -91,7 +91,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
@@ -99,184 +99,4 @@ export const registerActions = async () => {
//set busy to false in case of crash or cancel
params.ticket.get("opendiscord:busy").value = false
})
-}
-
-export const registerVerifyBars = async () => {
- //CLAIM TICKET TICKET MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:claim-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.claim
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when already claimed
- if (ticket.get("opendiscord:claimed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start claiming ticket
- if (params.data == "reason"){
- //claim with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:claim-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
- }else{
- //claim without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:claim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").failure.add([
- new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- })
- ])
-
- //CLAIM TICKET UNCLAIM MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:claim-ticket-unclaim-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-unclaim-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.claim
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when already claimed
- if (ticket.get("opendiscord:claimed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start claiming ticket
- if (params.data == "reason"){
- //claim with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:claim-ticket-reason").build("unclaim-message",{guild,channel,user,ticket}))
- }else{
- //claim without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:claim-ticket").run("unclaim-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("unclaim-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").failure.add([
- new api.ODWorker("opendiscord:back-to-unclaim-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason}))
- })
- ])
}
\ No newline at end of file
diff --git a/src/actions/clearTickets.ts b/src/actions/clearTickets.ts
index f2fac57..3c15e2b 100644
--- a/src/actions/clearTickets.ts
+++ b/src/actions/clearTickets.ts
@@ -1,15 +1,15 @@
///////////////////////////////////////
//CLEAR TICKETS SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:clear-tickets"))
opendiscord.actions.get("opendiscord:clear-tickets").workers.add([
- new api.ODWorker("opendiscord:clear-tickets",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:clear-tickets",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,filter,list} = params
await opendiscord.events.get("onTicketsClear").emit([list,user,channel,filter])
@@ -43,21 +43,21 @@ export const registerActions = async () => {
instance.list = nameList
await opendiscord.events.get("afterTicketsCleared").emit([list,user,channel,filter])
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,filter,list} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:clear-logs").build(source,{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 ?? []}))
}
}),
- new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,filter,list} = params
opendiscord.log(user.displayName+" cleared "+list.length+" tickets!","info",[
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"filter",value:filter}
])
})
diff --git a/src/actions/closeTicket.ts b/src/actions/closeTicket.ts
index e09bb2c..0c1e959 100644
--- a/src/actions/closeTicket.ts
+++ b/src/actions/closeTicket.ts
@@ -1,16 +1,17 @@
///////////////////////////////////////
//TICKET CLOSING SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:close-ticket"))
opendiscord.actions.get("opendiscord:close-ticket").workers.add([
- new api.ODWorker("opendiscord:close-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:close-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to close ticket! Open Ticket doesn't support threads!")
@@ -25,29 +26,34 @@ export const registerActions = async () => {
ticket.get("opendiscord:reopened-by").value = null
ticket.get("opendiscord:reopened-on").value = null
- if (source == "autoclose") ticket.get("opendiscord:autoclosed").value = true
+ if (origin == "autoclose") ticket.get("opendiscord:autoclosed").value = true
ticket.get("opendiscord:open").value = false
ticket.get("opendiscord:busy").value = true
//update stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-closed",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-closed",user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-closed",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-closed",user.id,1,"increase")
- //update category
+ //calculate & update category
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
- const closeCategory = ticket.option.get("opendiscord:channel-category-closed").value
- if (closeCategory !== ""){
- try {
- channel.setParent(closeCategory,{lockPermissions:false})
- ticket.get("opendiscord:category-mode").value = "closed"
- ticket.get("opendiscord:category").value = closeCategory
- }catch(e){
- opendiscord.log("Unable to move ticket to 'closed category'!","error",[
+ const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("close-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
+ if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
+ const originalCategoryName = channel.parent?.name ?? ""
+ const newCategoryName = categoryResult.newCategory?.name ?? ""
+ try{
+ await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
+ process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
+ })
+ ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
+ ticket.get("opendiscord:category").value = categoryResult.newCategoryId
+ }catch(err){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-close",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
+ opendiscord.log("Unable to move ticket to closed category.","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
- {key:"categoryid",value:closeCategory}
+ {key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
}
@@ -93,7 +99,7 @@ export const registerActions = async () => {
ticket.get("opendiscord:participants").value.forEach((participant) => {
//all participants that aren't roles/admins => readonly (OR non-viewable when enabled)
if (participant.type == "user"){
- if (generalConfig.data.system.removeParticipantsOnClose) permissions.push({
+ if (generalConfig.data.ticketSystem.removeParticipantsOnClose) permissions.push({
type:discord.OverwriteType.Member,
id:participant.id,
allow:[],
@@ -109,44 +115,39 @@ export const registerActions = async () => {
})
channel.permissionOverwrites.set(permissions)
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket closing!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(source,{guild,channel,user,ticket,reason})).message)
+ if (params.sendMessage){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(origin,{guild,channel,user,ticket,reason})).message)
+ if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
+ messageType:"close-message",
+ messageOrigin:"other",
+ messageAuthor:user.id,
+ messageReason:reason
+ },false)
+ }
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketClosed").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" closed a ticket!","info",[
@@ -155,7 +156,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
@@ -163,172 +164,4 @@ export const registerActions = async () => {
//set busy to false in case of crash or cancel
params.ticket.get("opendiscord:busy").value = false
})
-}
-
-export const registerVerifyBars = async () => {
- //CLOSE TICKET TICKET MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:close-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").success.add([
- new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => {
- const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.close,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when already closed
- if (ticket.get("opendiscord:closed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:lang.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when not allowed because of missing messages
- if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
- const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
- if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- }
-
- //start closing ticket
- if (params.data == "reason"){
- //close with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:close-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
- }else{
- //close without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:close-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").failure.add([
- new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- })
- ])
-
- //CLOSE TICKET REOPEN MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:close-ticket-reopen-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").success.add([
- new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => {
- const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.close,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when already closed
- if (ticket.get("opendiscord:closed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:lang.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when not allowed because of missing messages
- if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
- const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
- if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- }
-
- //start closing ticket
- if (params.data == "reason"){
- //close with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:close-ticket-reason").build("reopen-message",{guild,channel,user,ticket}))
- }else{
- //close without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:close-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("reopen-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").failure.add([
- new api.ODWorker("opendiscord:back-to-reopen-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
- })
- ])
}
\ No newline at end of file
diff --git a/src/actions/createTicket.ts b/src/actions/createTicket.ts
index 2e62699..c8ff9ca 100644
--- a/src/actions/createTicket.ts
+++ b/src/actions/createTicket.ts
@@ -1,63 +1,36 @@
///////////////////////////////////////
//TICKET CREATION SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:create-ticket"))
opendiscord.actions.get("opendiscord:create-ticket").workers.add([
- new api.ODWorker("opendiscord:create-ticket",3,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:create-ticket",3,async (instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
await opendiscord.events.get("onTicketCreate").emit([user])
await opendiscord.events.get("onTicketChannelCreation").emit([option,user])
//get channel properties
- const channelPrefix = option.get("opendiscord:channel-prefix").value
- const channelCategory = option.get("opendiscord:channel-category").value
- const channelBackupCategory = option.get("opendiscord:channel-category-backup").value
const channelTopicText = option.get("opendiscord:channel-topic").value
- const channelSuffix = await opendiscord.options.suffix.getSuffixFromOption(option,user,guild)
- const channelName = channelPrefix+channelSuffix
- //handle category
- let category: string|null = null
- let categoryMode: "backup"|"normal"|null = null
- if (channelCategory != ""){
- //category enabled
- const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory)
- if (!normalCategory){
- //default category was not found
- opendiscord.log("Ticket Creation Error: Unable to find category! #1","error",[
- {key:"categoryid",value:channelCategory},
- {key:"backup",value:"false"}
- ])
- }else{
- //default category was found
- if (normalCategory.children.cache.size >= 50 && channelBackupCategory != ""){
- //use backup category
- const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory)
- if (!backupCategory){
- //default category was not found
- opendiscord.log("Ticket Creation Error: Unable to find category! #2","error",[
- {key:"categoryid",value:channelBackupCategory},
- {key:"backup",value:"true"}
- ])
- }else{
- category = backupCategory.id
- categoryMode = "backup"
- }
- }else{
- //use default category
- category = normalCategory.id
- categoryMode = "normal"
- }
- }
- }
+ //calculate channel name
+ const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("create-ticket",{guild,user,option,channel:null,ticket:null,currentChannelName:null})
+ if (!channelNameResult) return opendiscord.log("Ticket Creation Error: Unable to calculate ticket name.","error")
+ const channelName = (channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined") ? channelNameResult.newChannelName : "ot-unnamed-ticket"
+ const channelSuffix = (typeof channelNameResult.newChannelSuffix !== "undefined") ? channelNameResult.newChannelSuffix : "unknown"
+
+ //calculate category
+ const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("create-ticket",{guild,user,option,channel:null,ticket:null,currentCategoryId:null})
+ if (!categoryResult) return opendiscord.log("Ticket Creation Error: Unable to calculate ticket category.","error")
+ const ticketCategoryId = (categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined") ? categoryResult.newCategoryId : undefined
+ const ticketCategoryMode = (categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryMode !== "undefined") ? categoryResult.newCategoryMode : undefined
//handle permissions
const permissions: discord.OverwriteResolvable[] = [{
@@ -118,15 +91,15 @@ export const registerActions = async () => {
//handle channel topic
const channelTopics: string[] = []
- if (generalConfig.data.system.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.system.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.system.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.system.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.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.showOptionName) channelTopics.push(option.get("opendiscord:name").value)
+ if (generalConfig.data.ticketSystem.channelTopic.showOptionDescription) channelTopics.push(option.get("opendiscord:description").value)
+ if (generalConfig.data.ticketSystem.channelTopic.showOptionTopic) channelTopics.push(channelTopicText)
+ if (generalConfig.data.ticketSystem.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.get("opendiscord:none").renderDisplayName())
+ if (generalConfig.data.ticketSystem.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+lang.getTranslation("params.uppercase.open"))
+ if (generalConfig.data.ticketSystem.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+lang.getTranslation("params.uppercase.noone"))
+ if (generalConfig.data.ticketSystem.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+lang.getTranslation("params.uppercase.no"))
+ if (generalConfig.data.ticketSystem.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(user.id))
+ 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
const channel = await guild.channels.create({
@@ -134,7 +107,7 @@ export const registerActions = async () => {
name:channelName,
nsfw:false,
topic:(channelTopics.length > 0) ? channelTopics.join(" โข ") : undefined,
- parent:category,
+ parent:ticketCategoryId,
reason:"Ticket Created By "+user.displayName,
permissionOverwrites:permissions,
rateLimitPerUser:slowMode
@@ -148,6 +121,7 @@ export const registerActions = async () => {
new api.ODTicketData("opendiscord:ticket-message",null),
new api.ODTicketData("opendiscord:participants",participants),
new api.ODTicketData("opendiscord:channel-suffix",channelSuffix),
+ new api.ODTicketData("opendiscord:channel-renamed",null),
new api.ODTicketData("opendiscord:previous-creators",[]),
new api.ODTicketData("opendiscord:open",true),
@@ -167,8 +141,8 @@ export const registerActions = async () => {
new api.ODTicketData("opendiscord:pinned-on",null),
new api.ODTicketData("opendiscord:for-deletion",false),
- new api.ODTicketData("opendiscord:category",category),
- new api.ODTicketData("opendiscord:category-mode",categoryMode),
+ new api.ODTicketData("opendiscord:category",ticketCategoryId ?? null),
+ new api.ODTicketData("opendiscord:category-mode",ticketCategoryMode ?? null),
new api.ODTicketData("opendiscord:autoclose-enabled",option.get("opendiscord:autoclose-enable-hours").value),
new api.ODTicketData("opendiscord:autoclose-hours",(option.get("opendiscord:autoclose-enable-hours").value ? option.get("opendiscord:autoclose-hours").value : 0)),
@@ -184,8 +158,8 @@ export const registerActions = async () => {
])
//manage stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-created",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-created",user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-created",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-created",user.id,1,"increase")
//manage bot permissions
await opendiscord.events.get("onTicketPermissionsCreated").emit([option,opendiscord.permissions,channel,user])
@@ -197,7 +171,7 @@ export const registerActions = async () => {
instance.ticket = ticket
opendiscord.tickets.add(ticket)
}),
- new api.ODWorker("opendiscord:send-ticket-message",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:send-ticket-message",2,async (instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
const {ticket,channel} = instance
@@ -207,17 +181,23 @@ export const registerActions = async () => {
//check if ticket message is enabled
if (!option.get("opendiscord:ticket-message-enabled").value) return
try {
- const msg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build(source,{guild,channel,user,ticket})).message)
+ const ticketMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build(origin,{guild,channel,user,ticket})).message)
- ticket.get("opendiscord:ticket-message").value = msg.id
+ if (ticketMsg) await interactiveMsgState.setMsgState({channel,message:ticketMsg},{
+ messageType:"ticket-message",
+ messageOrigin:"other",
+ messageAuthor:user.id
+ },false)
+
+ ticket.get("opendiscord:ticket-message").value = ticketMsg.id
//pin ticket message (if required)
- if (generalConfig.data.system.pinFirstTicketMessage && msg.pinnable) await msg.pin("Ticket Message")
+ if (generalConfig.data.ticketSystem.pinFirstTicketMessage && ticketMsg.pinnable) await ticketMsg.pin("Ticket Message")
//manage stats
- await opendiscord.stats.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")
- await opendiscord.events.get("afterTicketMainMessageCreated").emit([ticket,msg,channel,user])
+ await opendiscord.events.get("afterTicketMainMessageCreated").emit([ticket,ticketMsg,channel,user])
}catch(err){
process.emit("uncaughtException",err)
//something went wrong while sending the ticket message
@@ -225,20 +205,22 @@ export const registerActions = async () => {
}
await opendiscord.events.get("afterTicketCreated").emit([ticket,user,channel])
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
const {ticket,channel} = instance
+ if (!ticket || !channel) return opendiscord.log("Ticket Creation Error: Unable to send ticket message. Previous worker failed!","error")
+
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-logs").build(source,{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
- if (generalConfig.data.system.messages.creation.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-dm").build(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
const {ticket,channel} = instance
@@ -249,7 +231,7 @@ export const registerActions = async () => {
{key:"userid",value:user.id,hidden:true},
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"option",value:option.id.value}
])
})
diff --git a/src/actions/createTicketPermissions.ts b/src/actions/createTicketPermissions.ts
index 2c1bb06..0617124 100644
--- a/src/actions/createTicketPermissions.ts
+++ b/src/actions/createTicketPermissions.ts
@@ -1,13 +1,13 @@
///////////////////////////////////////
//TICKET CREATION SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:create-ticket-permissions"))
opendiscord.actions.get("opendiscord:create-ticket-permissions").workers.add([
- new api.ODWorker("opendiscord:check-blacklist",4,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:check-blacklist",4,(instance,params,origin,cancel) => {
if (!params.option.get("opendiscord:allow-blacklisted-users").value && opendiscord.blacklist.exists(params.user.id)){
instance.valid = false
instance.reason = "blacklist"
@@ -19,7 +19,7 @@ export const registerActions = async () => {
return cancel()
}
}),
- new api.ODWorker("opendiscord:check-cooldown",3,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:check-cooldown",3,(instance,params,origin,cancel) => {
const cooldown = opendiscord.cooldowns.get("opendiscord:option-cooldown_"+params.option.id.value)
if (cooldown && cooldown instanceof api.ODTimeoutCooldown && cooldown.use(params.user.id)){
instance.valid = false
@@ -36,16 +36,16 @@ export const registerActions = async () => {
return cancel()
}
}),
- new api.ODWorker("opendiscord:check-global-limits",2,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:check-global-limits",2,(instance,params,origin,cancel) => {
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 globalTicketCount = allTickets.length
const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.exists("opendiscord:opened-by") && (ticket.get("opendiscord:opened-by").value == params.user.id))
const userTicketCount = userTickets.length
- if (globalTicketCount >= generalConfig.data.system.limits.globalMaximum){
+ if (globalTicketCount >= generalConfig.data.ticketSystem.limits.globalMaximum){
instance.valid = false
instance.reason = "global-limit"
opendiscord.log(params.user.displayName+" tried to create a ticket but reached the limit!","info",[
@@ -55,7 +55,7 @@ export const registerActions = async () => {
{key:"limit",value:"global"}
])
return cancel()
- }else if (userTicketCount >= generalConfig.data.system.limits.userMaximum){
+ }else if (userTicketCount >= generalConfig.data.ticketSystem.limits.userMaximum){
instance.valid = false
instance.reason = "global-user-limit"
opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[
@@ -67,7 +67,7 @@ export const registerActions = async () => {
return cancel()
}
}),
- new api.ODWorker("opendiscord:check-option-limits",1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:check-option-limits",1,(instance,params,origin,cancel) => {
if (!params.option.exists("opendiscord:limits-enabled") || !params.option.get("opendiscord:limits-enabled").value) return
const allTickets = opendiscord.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value)
@@ -97,7 +97,7 @@ export const registerActions = async () => {
return cancel()
}
}),
- new api.ODWorker("opendiscord:valid",0,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:valid",0,(instance,params,origin,cancel) => {
instance.valid = true
instance.reason = null
cancel()
diff --git a/src/actions/createTranscript.ts b/src/actions/createTranscript.ts
index 825a142..2bbcb3f 100644
--- a/src/actions/createTranscript.ts
+++ b/src/actions/createTranscript.ts
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TRANSCRIPT CREATION SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:create-transcript"))
opendiscord.actions.get("opendiscord:create-transcript").workers.add([
- new api.ODWorker("opendiscord:select-compiler",4,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:select-compiler",4,async (instance,params,origin,cancel) => {
const {channel,user,ticket} = params
if (channel.type != discord.ChannelType.GuildText) return cancel()
if (!transcriptConfig.data.general.enabled) return cancel()
@@ -29,10 +29,15 @@ export const registerActions = async () => {
if (transcriptConfig.data.general.mode == "text") instance.compiler = opendiscord.transcripts.get("opendiscord:text-compiler")
else if (transcriptConfig.data.general.mode == "html") instance.compiler = opendiscord.transcripts.get("opendiscord:html-compiler")
}),
- new api.ODWorker("opendiscord:init-transcript",3,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:init-transcript",3,async (instance,params,origin,cancel) => {
const {channel,user,ticket} = params
if (channel.type != discord.ChannelType.GuildText) return cancel()
if (!transcriptConfig.data.general.enabled) return cancel()
+ if (!instance.compiler){
+ instance.success = false
+ cancel()
+ throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:init-transcript) => Instance is missing transcript compiler!")
+ }
//run transcript compiler init()
await opendiscord.events.get("onTranscriptInit").emit([opendiscord.transcripts,ticket,channel,user])
@@ -63,7 +68,7 @@ export const registerActions = async () => {
}
await opendiscord.events.get("afterTranscriptInitiated").emit([opendiscord.transcripts,ticket,channel,user])
}),
- new api.ODWorker("opendiscord:compile-transcript",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:compile-transcript",2,async (instance,params,origin,cancel) => {
const {channel,user,ticket} = params
if (channel.type != discord.ChannelType.GuildText) return cancel()
if (!instance.compiler){
@@ -71,6 +76,11 @@ export const registerActions = async () => {
cancel()
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:compile-transcript) => Instance is missing transcript compiler!")
}
+ if (typeof instance.initData == "undefined"){
+ instance.success = false
+ cancel()
+ throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:compile-transcript) => Instance is missing transcript initData!")
+ }
//run transcript compiler compile()
await opendiscord.events.get("onTranscriptCompile").emit([opendiscord.transcripts,ticket,channel,user])
@@ -93,15 +103,31 @@ export const registerActions = async () => {
}
await opendiscord.events.get("afterTranscriptCompiled").emit([opendiscord.transcripts,ticket,channel,user])
}),
- new api.ODWorker("opendiscord:ready-transcript",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:ready-transcript",1,async (instance,params,origin,cancel) => {
+ if (!instance.compiler){
+ instance.success = false
+ cancel()
+ throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript compiler! (1)")
+ }
if (!instance.result){
instance.success = false
cancel()
- throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript result!")
+ throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript result! (1)")
}
//run transcript compiler ready()
utilities.runAsync(async () => {
+ if (!instance.compiler){
+ instance.success = false
+ cancel()
+ throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript compiler! (2)")
+ }
+ if (!instance.result){
+ instance.success = false
+ cancel()
+ throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript result! (2)")
+ }
+
await opendiscord.events.get("onTranscriptReady").emit([opendiscord.transcripts,instance.result.ticket,instance.result.channel,instance.result.user])
if (instance.compiler.ready){
try{
@@ -109,9 +135,9 @@ export const registerActions = async () => {
//send channel message
if (transcriptConfig.data.general.enableChannel && channelMessage){
- if (instance.pendingMessage && instance.pendingMessage.message && instance.pendingMessage.success){
+ if (instance.pendingMessage && instance.pendingMessage.success){
//edit "pending" message to be the "ready" message
- instance.pendingMessage.message.edit(channelMessage.message)
+ instance.pendingMessage.message.edit(utilities.getMessageFromBuildResult(channelMessage,"message"))
}else{
//send ready message to channel
const post = opendiscord.posts.get("opendiscord:transcripts")
@@ -149,11 +175,11 @@ export const registerActions = async () => {
})
//update stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:transcripts-created",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:transcripts-created",params.user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:transcripts-created",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:transcripts-created",params.user.id,1,"increase")
await opendiscord.events.get("afterTranscriptCreated").emit([opendiscord.transcripts,instance.result.ticket,instance.result.channel,instance.result.user])
}),
- new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {user,channel,ticket} = params
opendiscord.log(user.displayName+" created a transcript!","info",[
{key:"user",value:user.username},
@@ -161,8 +187,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"option",value:ticket.option.id.value},
- {key:"method",value:source,hidden:true},
- {key:"compiler",value:instance.compiler.id.value},
+ {key:"method",value:origin,hidden:true},
+ {key:"compiler",value:instance.compiler?.id.value ?? ""},
])
})
])
diff --git a/src/actions/deleteTicket.ts b/src/actions/deleteTicket.ts
index 68b0d16..500ab61 100644
--- a/src/actions/deleteTicket.ts
+++ b/src/actions/deleteTicket.ts
@@ -1,16 +1,16 @@
///////////////////////////////////////
//TICKET DELETION SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:delete-ticket"))
opendiscord.actions.get("opendiscord:delete-ticket").workers.add([
- new api.ODWorker("opendiscord:delete-ticket",3,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:delete-ticket",3,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to delete ticket! Open Ticket doesn't support threads!")
@@ -20,31 +20,18 @@ export const registerActions = async () => {
ticket.get("opendiscord:for-deletion").value = true
ticket.get("opendiscord:busy").value = true
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket deletion!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(source,{guild,channel,user,ticket,reason})).message)
+ if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(origin,{guild,channel,user,ticket,reason})).message)
//create transcript
if (!params.withoutTranscript){
- const transcriptRes = await opendiscord.actions.get("opendiscord:create-transcript").run(source,{guild,channel,user,ticket})
+ const transcriptRes = await opendiscord.actions.get("opendiscord:create-transcript").run(origin,{guild,channel,user,ticket})
//transcript failure
if (typeof transcriptRes.success == "boolean" && !transcriptRes.success && transcriptRes.compiler){
const {compiler} = transcriptRes
- await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message)
+ await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transcript-error").build(origin,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message)
.catch((reason) => opendiscord.log("Unable to send transcript failure to ticket channel!","error",[{key:"id",value:channel.id}]))
//undo deletion
@@ -59,8 +46,8 @@ export const registerActions = async () => {
}
//update stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-deleted",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-deleted",user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-deleted",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-deleted",user.id,1,"increase")
//delete ticket from manager
opendiscord.tickets.remove(ticket.id)
@@ -68,21 +55,21 @@ export const registerActions = async () => {
//delete permissions from manager
await (await import("../data/framework/permissionLoader.js")).removeTicketPermissions(ticket)
}),
- new api.ODWorker("opendiscord:discord-logs",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",2,async (instance,params,origin,cancel) => {
//logs before channel deletion => channel might still be used in log embeds
const {guild,channel,user,ticket,reason} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:delete-channel",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
//delete channel & events
await opendiscord.events.get("onTicketChannelDeletion").emit([ticket,channel,user])
@@ -94,7 +81,7 @@ export const registerActions = async () => {
await opendiscord.events.get("afterTicketDeleted").emit([ticket,user,reason])
}),
- new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" deleted a ticket!","info",[
@@ -103,7 +90,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"transcript",value:(!params.withoutTranscript).toString()},
])
})
@@ -113,357 +100,4 @@ export const registerActions = async () => {
params.ticket.get("opendiscord:busy").value = false
params.ticket.get("opendiscord:for-deletion").value = false
})
-}
-
-export const registerVerifyBars = async () => {
- //DELETE TICKET TICKET MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").success.add([
- new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
- const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //don't allow deleteWithoutTranscript to non-global-admins when enabled
- if (params.data == "no-transcript" && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){
- 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"]}))
- return cancel()
- }
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when not allowed because of missing messages
- if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
- const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
- if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- }
-
- //start deleting ticket
- if (params.data == "reason"){
- //delete with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
- }else{
- //delete without reason
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript:(params.data == "no-transcript")})
- //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
- ticket.get("opendiscord:for-deletion").value = true
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").failure.add([
- new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- })
- ])
-
- //DELETE TICKET CLOSE MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-close-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").success.add([
- new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
- const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //don't allow deleteWithoutTranscript to non-global-admins when enabled
- if (params.data == "no-transcript" && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){
- 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"]}))
- return cancel()
- }
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when not allowed because of missing messages
- if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
- const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
- if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- }
-
- //start deleting ticket
- if (params.data == "reason"){
- //delete with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("close-message",{guild,channel,user,ticket}))
- }else{
- //delete without reason
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")})
- //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
- ticket.get("opendiscord:for-deletion").value = true
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("close-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").failure.add([
- new api.ODWorker("opendiscord:back-to-close-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason}))
- })
- ])
-
- //DELETE TICKET REOPEN MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-reopen-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").success.add([
- new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
- const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //don't allow deleteWithoutTranscript to non-global-admins when enabled
- if (params.data == "no-transcript" && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){
- 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"]}))
- return cancel()
- }
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not allowed because of missing messages
- if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
- const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
- if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- }
-
- //start deleting ticket
- if (params.data == "reason"){
- //delete with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("reopen-message",{guild,channel,user,ticket}))
- }else{
- //delete without reason
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")})
- //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
- ticket.get("opendiscord:for-deletion").value = true
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("reopen-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").failure.add([
- new api.ODWorker("opendiscord:back-to-reopen-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
- })
- ])
-
- //DELETE TICKET AUTOCLOSE MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-autoclose-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").success.add([
- new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
- const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //don't allow deleteWithoutTranscript to non-global-admins when enabled
- if (params.data == "no-transcript" && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){
- 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"]}))
- return cancel()
- }
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not allowed because of missing messages
- if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
- const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
- if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- }
-
- //start deleting ticket
- if (params.data == "reason"){
- //delete with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("autoclose-message",{guild,channel,user,ticket}))
- }else{
- //delete without reason
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")})
- //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
- ticket.get("opendiscord:for-deletion").value = true
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("autoclose-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").failure.add([
- new api.ODWorker("opendiscord:back-to-autoclose-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("other",{guild,channel,user,ticket}))
- })
- ])
}
\ No newline at end of file
diff --git a/src/actions/handleTranscriptErrors.ts b/src/actions/handleTranscriptErrors.ts
index bc0cf9a..d9548d0 100644
--- a/src/actions/handleTranscriptErrors.ts
+++ b/src/actions/handleTranscriptErrors.ts
@@ -1,76 +1,43 @@
///////////////////////////////////////
//TRANSCRIPT ERROR SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
+import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//TRANSCRIPT ERROR RETRY
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:transcript-error-retry",/^od:transcript-error-retry_([^_]+)/))
opendiscord.responders.buttons.get("opendiscord:transcript-error-retry").workers.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.delete
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:delete-ticket"]["source"]
+ new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,user,member} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+ //fetch data
+ const originalOrigin = instance.interaction.customId.split("_")[1] as api.ODActionManagerIdMappings["opendiscord:delete-ticket"]["origin"]
+
//start deleting ticket (without reason)
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false})
- //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
- ticket.get("opendiscord:for-deletion").value = true
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalOrigin,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false})
+
+ ticket.get("opendiscord:for-deletion").value = true //disable ticket message buttons
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Retried)"}))
-
}),
- new api.ODWorker("opendiscord:logs",-1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,async (instance,params,origin,cancel) => {
const {user,channel} = instance
if (channel.isDMBased()) return
opendiscord.log(user.displayName+" retried deleting a ticket with transcript!","info",[
@@ -78,7 +45,7 @@ export const registerButtonResponders = async () => {
{key:"userid",value:user.id,hidden:true},
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
@@ -86,68 +53,35 @@ export const registerButtonResponders = async () => {
//TRANSCRIPT ERROR CONTINUE
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:transcript-error-continue",/^od:transcript-error-continue_([^_]+)/))
opendiscord.responders.buttons.get("opendiscord:transcript-error-continue").workers.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.delete
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
- const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:delete-ticket"]["source"]
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
- //start deleting ticket (without reason)
+ //fetch data
+ const originalOrigin = instance.interaction.customId.split("_")[1] as api.ODActionManagerIdMappings["opendiscord:delete-ticket"]["origin"]
+
+ //start deleting ticket (without reason & without transcript)
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true})
- //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
- ticket.get("opendiscord:for-deletion").value = true
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalOrigin,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true})
+
+ ticket.get("opendiscord:for-deletion").value = true //disable ticket message buttons
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Continued)"}))
}),
- new api.ODWorker("opendiscord:logs",-1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,async (instance,params,origin,cancel) => {
const {user,channel} = instance
if (channel.isDMBased()) return
opendiscord.log(user.displayName+" continued deleting a ticket without transcript!","info",[
@@ -155,7 +89,7 @@ export const registerButtonResponders = async () => {
{key:"userid",value:user.id,hidden:true},
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/actions/handleVerifyBar.ts b/src/actions/handleVerifyBar.ts
index 2794d71..3eb6960 100644
--- a/src/actions/handleVerifyBar.ts
+++ b/src/actions/handleVerifyBar.ts
@@ -1,32 +1,22 @@
///////////////////////////////////////
//VERIFYBAR SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
+import * as discord from "discord.js"
-export const registerButtonResponders = async () => {
- //VERIFYBAR SUCCESS
- opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:verifybar-success",/^od:verifybar-success_([^_]+)/))
- opendiscord.responders.buttons.get("opendiscord:verifybar-success").workers.add(
- new api.ODWorker("opendiscord:handle-verifybar",0,async (instance,params,source,cancel) => {
- const id = instance.interaction.customId.split("_")[1]
- const customData = instance.interaction.customId.split("_")[2] as string|undefined
+export async function registerButtonResponders(){
+ //HANDLE VERIFYBAR BUTTON
+ opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:verifybar-button",/^od:verifybar\|([^|]+)\|([^|]+)/))
+ opendiscord.responders.buttons.get("opendiscord:verifybar-button").workers.add(
+ new api.ODWorker("opendiscord:handle-verifybar",0,async (instance,params,origin,cancel) => {
+ const match = /^od:verifybar\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
+ if (!match) return cancel()
+ const verifyBarId = match[1]
+ const verifyButtonId = match[2]
- const verifybar = opendiscord.verifybars.get(id)
+ const verifybar = opendiscord.verifybars.get(verifyBarId)
if (!verifybar) return
- if (verifybar.success) await verifybar.success.executeWorkers(instance,"verifybar",{data:customData ?? null,verifybarMessage:instance.message})
- })
- )
-
- //VERIFYBAR FAILURE
- opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:verifybar-failure",/^od:verifybar-failure_([^_]+)/))
- opendiscord.responders.buttons.get("opendiscord:verifybar-failure").workers.add(
- new api.ODWorker("opendiscord:handle-verifybar",0,async (instance,params,source,cancel) => {
- const id = instance.interaction.customId.split("_")[1]
- const customData = instance.interaction.customId.split("_")[2] as string|undefined
-
- const verifybar = opendiscord.verifybars.get(id)
- if (!verifybar) return
- if (verifybar.failure) await verifybar.failure.executeWorkers(instance,"verifybar",{data:customData ?? null,verifybarMessage:instance.message})
+ await verifybar.activate(instance,verifyButtonId)
})
)
}
\ No newline at end of file
diff --git a/src/actions/moveTicket.ts b/src/actions/moveTicket.ts
index 591aef6..2679368 100644
--- a/src/actions/moveTicket.ts
+++ b/src/actions/moveTicket.ts
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET MOVING SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:move-ticket"))
opendiscord.actions.get("opendiscord:move-ticket").workers.add([
- new api.ODWorker("opendiscord:move-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:move-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to move ticket! Open Ticket doesn't support threads!")
@@ -17,78 +17,31 @@ export const registerActions = async () => {
ticket.option = data
//update stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-moved",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-moved",user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-moved",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-moved",user.id,1,"increase")
- //get new channel properties
- const channelPrefix = ticket.option.get("opendiscord:channel-prefix").value
- const channelSuffix = ticket.get("opendiscord:channel-suffix").value
- const channelCategory = ticket.option.get("opendiscord:channel-category").value
- const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value
- const rawClaimCategory = ticket.option.get("opendiscord:channel-categories-claimed").value.find((c) => c.user == user.id)
- const claimCategory = (rawClaimCategory) ? rawClaimCategory.category : null
- const closeCategory = ticket.option.get("opendiscord:channel-category-closed").value
- const channelTopic = ticket.option.get("opendiscord:channel-topic").value
-
- //handle category
- let category: string|null = null
- let categoryMode: "backup"|"normal"|"closed"|"claimed"|null = null
- if (claimCategory){
- //use claim category
- category = claimCategory
- categoryMode = "claimed"
- }else if (closeCategory != "" && ticket.get("opendiscord:closed").value){
- //use close category
- category = closeCategory
- categoryMode = "closed"
- }else if (channelCategory != ""){
- //category enabled
- const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory)
- if (!normalCategory){
- //default category was not found
- opendiscord.log("Ticket Move Error: Unable to find category! #1","error",[
- {key:"categoryid",value:channelCategory},
- {key:"backup",value:"false"}
+ //calculate & update category
+ const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("move-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
+ if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
+ const originalCategoryName = channel.parent?.name ?? ""
+ const newCategoryName = categoryResult.newCategory?.name ?? ""
+ try{
+ await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
+ process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
+ })
+ ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
+ ticket.get("opendiscord:category").value = categoryResult.newCategoryId
+ }catch(err){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-move",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
+ opendiscord.log("Unable to move ticket to moved category.","error",[
+ {key:"channel",value:"#"+channel.name},
+ {key:"channelid",value:channel.id,hidden:true},
+ {key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
- }else{
- //default category was found
- if (normalCategory.children.cache.size >= 50 && channelBackupCategory != ""){
- //use backup category
- const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory)
- if (!backupCategory){
- //default category was not found
- opendiscord.log("Ticket Move Error: Unable to find category! #2","error",[
- {key:"categoryid",value:channelBackupCategory},
- {key:"backup",value:"true"}
- ])
- }else{
- category = backupCategory.id
- categoryMode = "backup"
- }
- }else{
- //use default category
- category = normalCategory.id
- categoryMode = "normal"
- }
}
}
- try {
- //only move category when not the same.
- if (channel.parentId != category) await utilities.timedAwait(channel.setParent(category,{lockPermissions:false}),2500,(err) => {
- opendiscord.log("Failed to change channel category on ticket move","error")
- })
- ticket.get("opendiscord:category-mode").value = categoryMode
- ticket.get("opendiscord:category").value = category
- }catch(e){
- opendiscord.log("Unable to move ticket to 'moved category'!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"categoryid",value:category ?? "/"}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
-
//handle permissions
const permissions: discord.OverwriteResolvable[] = [{
type:discord.OverwriteType.Role,
@@ -153,58 +106,50 @@ export const registerActions = async () => {
ticket.get("opendiscord:participants").value = participants
ticket.get("opendiscord:participants").refreshDatabase()
- //rename channel (and give error when crashed)
- const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
- const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
-
- const originalName = channel.name
- const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channelPrefix+channelSuffix)
- try{
- await utilities.timedAwait(channel.setName(newName),2500,(err) => {
- opendiscord.log("Failed to rename channel on ticket move","error")
- })
- }catch(err){
- await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName:newName})).message)
- }
-
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
+ //calculate channel name
+ const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("move-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
+ if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
+ const originalName = channel.name
+ const newName = channelNameResult.newChannelName
try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket moving!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
+ await utilities.timedAwait(channel.setName(newName),2500,(err) => {
+ opendiscord.log("Failed to rename channel on ticket move","error")
+ })
+ }catch(err){
+ opendiscord.log("Unable to rename channel while moving ticket! Waiting until ratelimit expires...","warning",[
+ {key:"oldName",value:originalName},
+ {key:"newName",value:newName}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
+
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(source,{guild,channel,user,ticket,reason,data})).message)
+ if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(origin,{guild,channel,user,ticket,reason,data})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketMoved").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" moved a ticket!","info",[
@@ -213,7 +158,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/actions/pinTicket.ts b/src/actions/pinTicket.ts
index a388ae0..6d52953 100644
--- a/src/actions/pinTicket.ts
+++ b/src/actions/pinTicket.ts
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET PINNING SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:pin-ticket"))
opendiscord.actions.get("opendiscord:pin-ticket").workers.add([
- new api.ODWorker("opendiscord:pin-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:pin-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to pin ticket! Open Ticket doesn't support threads!")
@@ -22,66 +23,66 @@ export const registerActions = async () => {
ticket.get("opendiscord:busy").value = true
//update stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-pinned",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-pinned",user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-pinned",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-pinned",user.id,1,"increase")
//move to top of category
if (channel.parent){
await channel.setPosition(0,{reason:"Ticket Pinned!"})
}
- //rename channel (and give error when crashed)
- const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
- const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
-
- const originalName = channel.name
- const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channel.name)
- try{
- await utilities.timedAwait(channel.setName(newName),2500,(err) => {
- opendiscord.log("Failed to rename channel on ticket pin","error")
- })
- }catch(err){
- await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message)
- }
-
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
+ //calculate channel name
+ const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("pin-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
+ if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
+ const originalName = channel.name
+ const newName = channelNameResult.newChannelName
try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket pinning!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"message",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
+ await utilities.timedAwait(channel.setName(newName),2500,(err) => {
+ opendiscord.log("Failed to rename channel on ticket pin","error")
+ })
+ }catch(err){
+ opendiscord.log("Unable to rename channel while pinning ticket! Waiting until ratelimit expires...","warning",[
+ {key:"oldName",value:originalName},
+ {key:"newName",value:newName}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
+
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(source,{guild,channel,user,ticket,reason})).message)
+ if (params.sendMessage){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(origin,{guild,channel,user,ticket,reason})).message)
+ if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
+ messageType:"pin-message",
+ messageOrigin:"other",
+ messageAuthor:user.id,
+ messageReason:reason
+ },false)
+ }
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketPinned").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" pinned a ticket!","info",[
@@ -90,192 +91,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
-}
-
-export const registerVerifyBars = async () => {
- //PIN TICKET TICKET MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:pin-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.pin
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when already pinned
- if (ticket.get("opendiscord:pinned").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start pinning ticket
- if (params.data == "reason"){
- //pin with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:pin-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
- }else{
- //pin without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:pin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").failure.add([
- new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- })
- ])
-
- //PIN TICKET UNPIN MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:pin-ticket-unpin-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-unpin-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.pin
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when already pinned
- if (ticket.get("opendiscord:pinned").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start pinning ticket
- if (params.data == "reason"){
- //pin with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:pin-ticket-reason").build("unpin-message",{guild,channel,user,ticket}))
- }else{
- //pin without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:pin-ticket").run("unpin-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("unpin-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").failure.add([
- new api.ODWorker("opendiscord:back-to-unpin-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason}))
- })
- ])
- opendiscord.actions.get("opendiscord:pin-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => {
- //set busy to false in case of crash or cancel
- params.ticket.get("opendiscord:busy").value = false
- })
}
\ No newline at end of file
diff --git a/src/actions/reactionRole.ts b/src/actions/reactionRole.ts
index 84760e1..8a0a116 100644
--- a/src/actions/reactionRole.ts
+++ b/src/actions/reactionRole.ts
@@ -1,15 +1,15 @@
///////////////////////////////////////
//REACTION ROLE SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:reaction-role"))
opendiscord.actions.get("opendiscord:reaction-role").workers.add([
- new api.ODWorker("opendiscord:reaction-role",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:reaction-role",2,async (instance,params,origin,cancel) => {
const {guild,user,option,overwriteMode} = params
const role = opendiscord.roles.get(option.id)
if (!role) throw new api.ODSystemError("ODAction(ot:reaction-role) => Unknown reaction role (ODRole)")
@@ -83,25 +83,25 @@ export const registerActions = async () => {
instance.result = result
await opendiscord.events.get("afterRolesUpdated").emit([user,role])
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,user,option,overwriteMode} = params
if (!instance.role || !instance.result) return
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-logs").build(source,{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
- if (generalConfig.data.system.messages.reactionRole.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-dm").build(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,option} = params
opendiscord.log(user.displayName+" updated his roles!","info",[
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"option",value:option.id.value}
])
})
diff --git a/src/actions/removeTicketUser.ts b/src/actions/removeTicketUser.ts
index 9a8ef9f..93737fc 100644
--- a/src/actions/removeTicketUser.ts
+++ b/src/actions/removeTicketUser.ts
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET REMOVE USER SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:remove-ticket-user"))
opendiscord.actions.get("opendiscord:remove-ticket-user").workers.add([
- new api.ODWorker("opendiscord:remove-ticket-user",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:remove-ticket-user",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to remove user from ticket! Open Ticket doesn't support threads!")
@@ -29,43 +29,31 @@ export const registerActions = async () => {
opendiscord.log("Failed to remove channel permission overwrites on remove-ticket-user","error")
}
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket user removal!","error",[
- {key:"channel",value:channel.id},
- {key:"message",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(source,{guild,channel,user,ticket,reason,data})).message)
+ if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(origin,{guild,channel,user,ticket,reason,data})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketUserRemoved").emit([ticket,user,data,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,data} = params
opendiscord.log(user.displayName+" removed "+data.displayName+" from a ticket!","info",[
@@ -74,7 +62,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/actions/renameTicket.ts b/src/actions/renameTicket.ts
index a110f16..7ffd071 100644
--- a/src/actions/renameTicket.ts
+++ b/src/actions/renameTicket.ts
@@ -1,72 +1,67 @@
///////////////////////////////////////
//TICKET RENAMING SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:rename-ticket"))
opendiscord.actions.get("opendiscord:rename-ticket").workers.add([
- new api.ODWorker("opendiscord:rename-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:rename-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to rename ticket! Open Ticket doesn't support threads!")
await opendiscord.events.get("onTicketRename").emit([ticket,user,channel,reason])
- //rename channel (and give error when crashed)
- const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
- const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
+ //update ticket
+ ticket.get("opendiscord:channel-renamed").value = data
- const originalName = channel.name
- const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(data)
- try{
- await utilities.timedAwait(channel.setName(newName),2500,(err) => {
- opendiscord.log("Failed to rename channel on ticket rename","error")
- })
- }catch(err){
- await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName:data})).message)
- }
-
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
+ //calculate channel name
+ const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("rename-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
+ if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
+ const originalName = channel.name
+ const newName = channelNameResult.newChannelName
try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket renaming!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
+ await utilities.timedAwait(channel.setName(newName),2500,(err) => {
+ opendiscord.log("Failed to rename channel on ticket rename","error")
+ })
+ }catch(err){
+ opendiscord.log("Unable to rename channel while renaming ticket! Waiting until ratelimit expires...","warning",[
+ {key:"oldName",value:originalName},
+ {key:"newName",value:newName}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
+
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(source,{guild,channel,user,ticket,reason,data})).message)
+ if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(origin,{guild,channel,user,ticket,reason,data})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketRenamed").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" renamed a ticket!","info",[
@@ -75,7 +70,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/actions/reopenTicket.ts b/src/actions/reopenTicket.ts
index 5112f66..75d06da 100644
--- a/src/actions/reopenTicket.ts
+++ b/src/actions/reopenTicket.ts
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET REOPENING SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:reopen-ticket"))
opendiscord.actions.get("opendiscord:reopen-ticket").workers.add([
- new api.ODWorker("opendiscord:reopen-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:reopen-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to reopen ticket! Open Ticket doesn't support threads!")
@@ -28,65 +29,37 @@ export const registerActions = async () => {
ticket.get("opendiscord:open").value = true
ticket.get("opendiscord:busy").value = true
- if (generalConfig.data.system.disableAutocloseAfterReopen){
+ if (generalConfig.data.ticketSystem.disableAutocloseAfterReopen){
//disable autoclose after reopen
ticket.get("opendiscord:autoclose-enabled").value = false
ticket.get("opendiscord:autoclose-hours").value = 0
}
//update stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-reopened",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-reopened",user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-reopened",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-reopened",user.id,1,"increase")
- //update category
+ //calculate & update category
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
- const channelCategory = ticket.option.get("opendiscord:channel-category").value
- const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value
- if (channelCategory !== ""){
- //category enabled
- try {
- const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory)
- if (!normalCategory){
- //default category was not found
- opendiscord.log("Ticket Reopening Error: Unable to find category! #1","error",[
- {key:"categoryid",value:channelCategory},
- {key:"backup",value:"false"}
- ])
- }else{
- //default category was found
- if (normalCategory.children.cache.size >= 49 && channelBackupCategory != ""){
- //use backup category
- const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory)
- if (!backupCategory){
- //default category was not found
- opendiscord.log("Ticket Reopening Error: Unable to find category! #2","error",[
- {key:"categoryid",value:channelBackupCategory},
- {key:"backup",value:"true"}
- ])
- }else{
- //use backup category
- channel.setParent(backupCategory,{lockPermissions:false})
- ticket.get("opendiscord:category-mode").value = "backup"
- ticket.get("opendiscord:category").value = backupCategory.id
- }
- }else{
- //use default category
- channel.setParent(normalCategory,{lockPermissions:false})
- ticket.get("opendiscord:category-mode").value = "normal"
- ticket.get("opendiscord:category").value = normalCategory.id
- }
- }
- }catch(e){
- opendiscord.log("Unable to move ticket to 'reopened category'!","error",[
+ const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("reopen-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
+ if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
+ const originalCategoryName = channel.parent?.name ?? ""
+ const newCategoryName = categoryResult.newCategory?.name ?? ""
+ try{
+ await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
+ process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
+ })
+ ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
+ ticket.get("opendiscord:category").value = categoryResult.newCategoryId
+ }catch(err){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-reopen",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
+ opendiscord.log("Unable to move ticket to reopened category.","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
+ {key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
- }else{
- channel.setParent(null,{lockPermissions:false})
- ticket.get("opendiscord:category-mode").value = null
- ticket.get("opendiscord:category").value = null
}
}
@@ -141,43 +114,38 @@ export const registerActions = async () => {
})
channel.permissionOverwrites.set(permissions)
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket reopening!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(source,{guild,channel,user,ticket,reason})).message)
+ if (params.sendMessage){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(origin,{guild,channel,user,ticket,reason})).message)
+ if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
+ messageType:"reopen-message",
+ messageOrigin:"other",
+ messageAuthor:user.id,
+ messageReason:reason
+ },false)
+ }
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketReopened").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" reopened a ticket!","info",[
@@ -186,280 +154,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
-}
-
-export const registerVerifyBars = async () => {
- //REOPEN TICKET TICKET MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.reopen
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not closed
- if (!ticket.get("opendiscord:closed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start reopening ticket
- if (params.data == "reason"){
- //reopen with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
- }else{
- //reopen without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:reopen-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").failure.add([
- new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- })
- ])
-
- //REOPEN TICKET CLOSE MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-close-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.reopen
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not closed
- if (!ticket.get("opendiscord:closed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start reopening ticket
- if (params.data == "reason"){
- //reopen with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("close-message",{guild,channel,user,ticket}))
- }else{
- //reopen without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:reopen-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("close-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").failure.add([
- new api.ODWorker("opendiscord:back-to-close-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason}))
- })
- ])
-
- //REOPEN TICKET AUTOCLOSE MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-autoclose-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.reopen
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not closed
- if (!ticket.get("opendiscord:closed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start reopening ticket
- if (params.data == "reason"){
- //reopen with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("autoclose-message",{guild,channel,user,ticket}))
- }else{
- //reopen without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:reopen-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("autoclose-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").failure.add([
- new api.ODWorker("opendiscord:back-to-autoclose-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("other",{guild,channel,user,ticket}))
- })
- ])
- opendiscord.actions.get("opendiscord:reopen-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => {
- //set busy to false in case of crash or cancel
- params.ticket.get("opendiscord:busy").value = false
- })
}
\ No newline at end of file
diff --git a/src/actions/transferTicket.ts b/src/actions/transferTicket.ts
index 85887dc..59ae605 100644
--- a/src/actions/transferTicket.ts
+++ b/src/actions/transferTicket.ts
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET TRANSFER SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:transfer-ticket"))
opendiscord.actions.get("opendiscord:transfer-ticket").workers.add([
- new api.ODWorker("opendiscord:transfer-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:transfer-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,newCreator} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to transfer ticket! Open Ticket doesn't support threads!")
@@ -33,12 +33,8 @@ export const registerActions = async () => {
}
//update stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-transferred",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-transferred",user.id,1,"increase")
-
- //get new channel properties
- const channelPrefix = ticket.option.get("opendiscord:channel-prefix").value
- const channelSuffix = ticket.get("opendiscord:channel-suffix").value
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-transferred",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-transferred",user.id,1,"increase")
//handle permissions
const permissions: discord.OverwriteResolvable[] = [{
@@ -93,48 +89,40 @@ export const registerActions = async () => {
opendiscord.log("Failed to reset channel permissions on ticket transfer!","error")
}
- //rename channel (and give error when crashed)
- const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
- const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
-
- const originalName = channel.name
- const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channelPrefix+channelSuffix)
- try{
- await utilities.timedAwait(channel.setName(newName),2500,(err) => {
- opendiscord.log("Failed to rename channel on ticket transfer","error")
- })
- }catch(err){
- await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-transfer",{guild,channel,user,originalName,newName:newName})).message)
- }
-
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
+ //calculate channel name
+ const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("transfer-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
+ if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
+ const originalName = channel.name
+ const newName = channelNameResult.newChannelName
try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket transferring!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
+ await utilities.timedAwait(channel.setName(newName),2500,(err) => {
+ opendiscord.log("Failed to rename channel on ticket transfer","error")
+ })
+ }catch(err){
+ opendiscord.log("Unable to rename channel while transferring ticket! Waiting until ratelimit expires...","warning",[
+ {key:"oldName",value:originalName},
+ {key:"newName",value:newName}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-transfer",{guild,channel,user,originalName,newName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
+
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transfer-message").build(source,{guild,channel,user,ticket,oldCreator,newCreator,reason})).message)
+ if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transfer-message").build(origin,{guild,channel,user,ticket,oldCreator,newCreator,reason})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketTransferred").emit([ticket,user,channel,oldCreator,newCreator,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newCreator,reason} = params
}),
- new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newCreator} = params
opendiscord.log(user.displayName+" transferred a ticket to '"+newCreator.displayName+"'!","info",[
@@ -143,7 +131,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/actions/unclaimTicket.ts b/src/actions/unclaimTicket.ts
index 6a04c1e..e91b4ef 100644
--- a/src/actions/unclaimTicket.ts
+++ b/src/actions/unclaimTicket.ts
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET UNCLAIMING SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:unclaim-ticket"))
opendiscord.actions.get("opendiscord:unclaim-ticket").workers.add([
- new api.ODWorker("opendiscord:unclaim-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:unclaim-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to unclaim ticket! Open Ticket doesn't support threads!")
@@ -21,97 +22,63 @@ export const registerActions = async () => {
ticket.get("opendiscord:claimed-on").value = null
ticket.get("opendiscord:busy").value = true
- //update category
+ //calculate & update category
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
- const channelCategory = ticket.option.get("opendiscord:channel-category").value
- const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value
- if (channelCategory !== ""){
- //category enabled
- try {
- const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory)
- if (!normalCategory){
- //default category was not found
- opendiscord.log("Ticket Unclaiming Error: Unable to find category! #1","error",[
- {key:"categoryid",value:channelCategory},
- {key:"backup",value:"false"}
- ])
- }else{
- //default category was found
- if (normalCategory.children.cache.size >= 49 && channelBackupCategory != ""){
- //use backup category
- const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory)
- if (!backupCategory){
- //default category was not found
- opendiscord.log("Ticket Unclaiming Error: Unable to find category! #2","error",[
- {key:"categoryid",value:channelBackupCategory},
- {key:"backup",value:"true"}
- ])
- }else{
- //use backup category
- channel.setParent(backupCategory,{lockPermissions:false})
- ticket.get("opendiscord:category-mode").value = "backup"
- ticket.get("opendiscord:category").value = backupCategory.id
- }
- }else{
- //use default category
- channel.setParent(normalCategory,{lockPermissions:false})
- ticket.get("opendiscord:category-mode").value = "normal"
- ticket.get("opendiscord:category").value = normalCategory.id
- }
- }
-
- }catch(e){
- opendiscord.log("Unable to move ticket to 'unclaimed category'!","error",[
+ const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("unclaim-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
+ if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
+ const originalCategoryName = channel.parent?.name ?? ""
+ const newCategoryName = categoryResult.newCategory?.name ?? ""
+ try{
+ await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
+ process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
+ })
+ ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
+ ticket.get("opendiscord:category").value = categoryResult.newCategoryId
+ }catch(err){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-unclaim",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
+ opendiscord.log("Unable to move ticket to unclaimed category.","error",[
{key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true}
+ {key:"channelid",value:channel.id,hidden:true},
+ {key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
- }else{
- channel.setParent(null,{lockPermissions:false})
- ticket.get("opendiscord:category-mode").value = null
- ticket.get("opendiscord:category").value = null
}
}
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket unclaiming!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(source,{guild,channel,user,ticket,reason})).message)
+ if (params.sendMessage){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(origin,{guild,channel,user,ticket,reason})).message)
+ if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
+ messageType:"unclaim-message",
+ messageOrigin:"other",
+ messageAuthor:user.id,
+ messageReason:reason
+ },false)
+ }
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketUnclaimed").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" unclaimed a ticket!","info",[
@@ -120,192 +87,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
-}
-
-export const registerVerifyBars = async () => {
- //UNCLAIM TICKET TICKET MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unclaim-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.unclaim
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not claimed
- if (!ticket.get("opendiscord:claimed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start unclaiming ticket
- if (params.data == "reason"){
- //unclaim with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unclaim-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
- }else{
- //unclaim without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unclaim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").failure.add([
- new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- })
- ])
-
- //UNCLAIM TICKET CLAIM MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unclaim-ticket-claim-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-claim-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.unclaim
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not claimed
- if (!ticket.get("opendiscord:claimed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start unclaiming ticket
- if (params.data == "reason"){
- //unclaim with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unclaim-ticket-reason").build("claim-message",{guild,channel,user,ticket}))
- }else{
- //unclaim without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unclaim-ticket").run("claim-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("claim-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").failure.add([
- new api.ODWorker("opendiscord:back-to-claim-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason}))
- })
- ])
- opendiscord.actions.get("opendiscord:unclaim-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => {
- //set busy to false in case of crash or cancel
- params.ticket.get("opendiscord:busy").value = false
- })
}
\ No newline at end of file
diff --git a/src/actions/unpinTicket.ts b/src/actions/unpinTicket.ts
index 931ef38..747754a 100644
--- a/src/actions/unpinTicket.ts
+++ b/src/actions/unpinTicket.ts
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET UNPINNING SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:unpin-ticket"))
opendiscord.actions.get("opendiscord:unpin-ticket").workers.add([
- new api.ODWorker("opendiscord:unpin-ticket",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:unpin-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to unpin ticket! Open Ticket doesn't support threads!")
@@ -21,58 +22,58 @@ export const registerActions = async () => {
ticket.get("opendiscord:pinned-on").value = null
ticket.get("opendiscord:busy").value = true
- //rename channel (and give error when crashed)
- const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
- const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
-
- const originalName = channel.name
- const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channel.name)
- try{
- await utilities.timedAwait(channel.setName(newName),2500,(err) => {
- opendiscord.log("Failed to rename channel on ticket unpin","error")
- })
- }catch(err){
- await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message)
- }
-
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
+ //calculate channel name
+ const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("unpin-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
+ if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
+ const originalName = channel.name
+ const newName = channelNameResult.newChannelName
try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on ticket unpinning!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
+ await utilities.timedAwait(channel.setName(newName),2500,(err) => {
+ opendiscord.log("Failed to rename channel on ticket unpin","error")
+ })
+ }catch(err){
+ opendiscord.log("Unable to rename channel while unpinning ticket! Waiting until ratelimit expires...","warning",[
+ {key:"oldName",value:originalName},
+ {key:"newName",value:newName}
])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
+
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(source,{guild,channel,user,ticket,reason})).message)
+ if (params.sendMessage){
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(origin,{guild,channel,user,ticket,reason})).message)
+ if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
+ messageType:"unpin-message",
+ messageOrigin:"other",
+ messageAuthor:user.id,
+ messageReason:reason
+ },false)
+ }
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketUnpinned").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{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
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(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" unpinned a ticket!","info",[
@@ -81,192 +82,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
-}
-
-export const registerVerifyBars = async () => {
- //UNPIN TICKET TICKET MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unpin-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.unpin
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not pinned
- if (!ticket.get("opendiscord:pinned").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start unpining ticket
- if (params.data == "reason"){
- //unpin with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unpin-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
- }else{
- //unpin without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unpin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").failure.add([
- new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- })
- ])
-
- //UNPIN TICKET PIN MESSAGE
- opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unpin-ticket-pin-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-pin-message"),!generalConfig.data.system.disableVerifyBars))
- opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").success.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.unpin
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- 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()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when not pinned
- if (!ticket.get("opendiscord:pinned").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //start unpinning ticket
- if (params.data == "reason"){
- //unpin with reason
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unpin-ticket-reason").build("pin-message",{guild,channel,user,ticket}))
- }else{
- //unpin without reason
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unpin-ticket").run("pin-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("pin-message",{guild,channel,user,ticket,reason:null}))
- }
- })
- ])
- opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").failure.add([
- new api.ODWorker("opendiscord:back-to-pin-message",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- const {verifybarMessage} = params
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason}))
- })
- ])
- opendiscord.actions.get("opendiscord:unpin-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => {
- //set busy to false in case of crash or cancel
- params.ticket.get("opendiscord:busy").value = false
- })
}
\ No newline at end of file
diff --git a/src/actions/updateTicketPriority.ts b/src/actions/updateTicketPriority.ts
index de328a7..76be4ec 100644
--- a/src/actions/updateTicketPriority.ts
+++ b/src/actions/updateTicketPriority.ts
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET TOPIC SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:update-ticket-priority"))
opendiscord.actions.get("opendiscord:update-ticket-priority").workers.add([
- new api.ODWorker("opendiscord:update-ticket-priority",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:update-ticket-priority",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newPriority,reason} = params
if (channel.isThread() || !(channel instanceof discord.TextChannel)) throw new api.ODSystemError("Unable to set priority of ticket! Open Ticket doesn't support threads!")
@@ -20,32 +20,37 @@ export const registerActions = async () => {
ticket.get("opendiscord:busy").value = true
if (newPriority) ticket.get("opendiscord:priority").value = newPriority.priority
- //rename channel (and give error when crashed)
- const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
- const priorityEmoji = newPriority.channelEmoji ?? ""
-
- const originalName = channel.name
- const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channel.name)
- try{
- await utilities.timedAwait(channel.setName(newName),2500,(err) => {
- opendiscord.log("Failed to rename channel on ticket priority update","error")
- })
- }catch(err){
- await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-priority",{guild,channel,user,originalName,newName})).message)
+ //calculate channel name
+ const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("priority-change",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
+ if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
+ const originalName = channel.name
+ const newName = channelNameResult.newChannelName
+ try{
+ await utilities.timedAwait(channel.setName(newName),2500,(err) => {
+ opendiscord.log("Failed to rename channel on priority change","error")
+ })
+ }catch(err){
+ opendiscord.log("Unable to rename channel while updating ticket priority! Waiting until ratelimit expires...","warning",[
+ {key:"oldName",value:originalName},
+ {key:"newName",value:newName}
+ ])
+ const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-priority",{guild,channel,user,originalName,newName})).message)
+ setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
+ }
}
//reply with new message
- if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:priority-set").build(source,{guild,channel,user,ticket,priority:newPriority,reason})).message)
+ if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:priority-set").build(origin,{guild,channel,user,ticket,priority:newPriority,reason})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketPriorityChanged").emit([ticket,user,channel,oldPriority,newPriority,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
}),
- new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newPriority} = params
opendiscord.log(user.displayName+" changed the priority of a ticket!","info",[
@@ -54,7 +59,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"priority",value:newPriority.id.value},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/actions/updateTicketTopic.ts b/src/actions/updateTicketTopic.ts
index 1b544b0..207a5d7 100644
--- a/src/actions/updateTicketTopic.ts
+++ b/src/actions/updateTicketTopic.ts
@@ -1,16 +1,16 @@
///////////////////////////////////////
//TICKET TOPIC SYSTEM
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
-export const registerActions = async () => {
+export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:update-ticket-topic"))
opendiscord.actions.get("opendiscord:update-ticket-topic").workers.add([
- new api.ODWorker("opendiscord:update-ticket-topic",2,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:update-ticket-topic",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newTopic} = params
if (channel.isThread() || !(channel instanceof discord.TextChannel)) throw new api.ODSystemError("Unable to set topic of ticket! Open Ticket doesn't support threads!")
@@ -29,28 +29,28 @@ export const registerActions = async () => {
//handle channel topic
const channelTopics: string[] = []
- if (generalConfig.data.system.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.system.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.system.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.system.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.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.showOptionName) channelTopics.push(ticket.option.get("opendiscord:name").value)
+ if (generalConfig.data.ticketSystem.channelTopic.showOptionDescription) channelTopics.push(ticket.option.get("opendiscord:description").value)
+ if (generalConfig.data.ticketSystem.channelTopic.showOptionTopic) channelTopics.push(ticket.get("opendiscord:topic").value)
+ 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.ticketSystem.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.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+(claimedBy ? discord.userMention(claimedBy) : lang.getTranslation("params.uppercase.noone")))
+ 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.ticketSystem.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(creator))
+ 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
channel.setTopic(channelTopics.join(" โข "),"Topic Changed")
//reply with new message
- if (params.sendMessage && newTopic) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:topic-set").build(source,{guild,channel,user,ticket,topic:newTopic})).message)
+ if (params.sendMessage && newTopic) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:topic-set").build(origin,{guild,channel,user,ticket,topic:newTopic})).message)
ticket.get("opendiscord:busy").value = false
if (newTopic) await opendiscord.events.get("afterTicketTopicChanged").emit([ticket,user,channel,oldTopic,newTopic])
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
}),
- new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newTopic} = params
if (newTopic) opendiscord.log(user.displayName+" changed the topic of a ticket!","info",[
@@ -59,7 +59,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"topic",value:newTopic},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/actions/utilities.ts b/src/actions/utilities.ts
new file mode 100644
index 0000000..8f87003
--- /dev/null
+++ b/src/actions/utilities.ts
@@ -0,0 +1,176 @@
+///////////////////////////////////////
+//OPEN TICKET UTILITY FUNCTIONS
+///////////////////////////////////////
+import {opendiscord, api, utilities} from "../index.js"
+import * as discord from "discord.js"
+
+/**Fetch the interactive message state. If not present, auto replies with error and returns `null`. When `null` is received, the worker should be returned and canceled. */
+export async function replyInteractiveMessageState(instance:api.ODButtonResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",channel:discord.TextBasedChannel,message:discord.Message|null,replacementCommandName:string){
+ //check message state
+ const {user,member,guild} = instance
+ const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
+
+ if (!message){
+ //TODO TRANSLATION!!!
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"Unable to locate message of interaction. Use the command `{0}` instead.".replace("{0}",replacementCommandName),layout:"simple",customTitle:"Message State Error"}))
+ return null
+ }
+
+ const state = await interactiveMsgState.getMsgState({channel,message})
+ if (!state){
+ //TODO TRANSLATION!!!
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"This interaction is no longer valid or has expired. Use the command `{0}` instead. It is normal to receive this error after a major Open Ticket update.".replace("{0}",replacementCommandName),layout:"simple",customTitle:"Message State Expired"}))
+ return null
+ }else return state
+}
+
+/**Check the permissions for this command. If not allowed, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyHasPermissions(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",commandName:keyof api.ODGeneralJsonConfig_SystemPermissions,settings?:api.ODPermissionSettings) {
+ //check permissions
+ const {user,member,channel,guild} = instance
+ const generalConfig = opendiscord.configs.get("opendiscord:general")
+ const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.permissions[commandName],"support",user,member,channel,guild,settings)
+
+ 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}))
+ else if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(origin,{guild,channel,user,permissions:["support"]}))
+ return false
+ }else return true
+}
+
+/**Check if channel is in guild/server. If not, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyIsInGuild(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other"){
+ //check is in guild/server
+ const {user,member,channel,guild} = instance
+
+ if (!guild){
+ if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(origin,{channel,user}))
+ return false
+ }else return true
+}
+
+/**Check if channel is valid ticket. If not, auto replies with error and returns `null`. When `null` is received, the worker should be returned and canceled. */
+export async function replyIsTicket(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other") {
+ //check if ticket exists
+ const {user,member,channel,guild} = instance
+ if (!channel) return null
+ const ticket = opendiscord.tickets.get(channel.id)
+
+ if (!ticket || channel.isDMBased()){
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build(origin,{guild,channel,user}))
+ return null
+ }else return ticket
+}
+
+/**Check if ticket is not busy and available. If not, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyTicketIsAvailable(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
+ //return when busy
+ const {user,member,channel,guild} = instance
+
+ if (ticket.get("opendiscord:busy").value){
+ if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build(origin,{guild,channel,user}))
+ return false
+ }else return true
+}
+
+/**Check if ticket is open. If closed, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyTicketMustBeOpen(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket){
+ //return when already closed
+ const {user,member,channel,guild} = instance
+ if (ticket.get("opendiscord:closed").value){
+ if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
+ return false
+ }else return true
+}
+
+/**Check if ticket is closed. If open, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyTicketMustBeClosed(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
+ //return when already open
+ const {user,member,channel,guild} = instance
+ if (!ticket.get("opendiscord:closed").value){
+ if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
+ return false
+ }else return true
+}
+
+/**Check if ticket is unclaimed. If claimed, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyTicketMustBeUnclaimed(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
+ //return when already claimed
+ const {user,member,channel,guild} = instance
+ if (ticket.get("opendiscord:claimed").value){
+ if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"}))
+ return false
+ }else return true
+}
+
+/**Check if ticket is claimed. If unclaimed, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyTicketMustBeClaimed(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
+ //return when already unclaimed
+ const {user,member,channel,guild} = instance
+ if (!ticket.get("opendiscord:claimed").value){
+ if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"}))
+ return false
+ }else return true
+}
+
+/**Check if ticket is unpinned. If pinned, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyTicketMustBeUnpinned(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
+ //return when already pinned
+ const {user,member,channel,guild} = instance
+ if (ticket.get("opendiscord:pinned").value){
+ if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"}))
+ return false
+ }else return true
+}
+
+/**Check if ticket is pinned. If unpinned, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyTicketMustBePinned(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
+ //return when already unpinned
+ const {user,member,channel,guild} = instance
+ if (!ticket.get("opendiscord:pinned").value){
+ if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"}))
+ return false
+ }else return true
+}
+
+/**Check if the ticket can be closed/deleted before a message has been sent by an admin or user. If not passing the test, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
+export async function replyMessageMustBeSentBeforeClose(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket,commandName:keyof api.ODGeneralJsonConfig_SystemPermissions) {
+ //return when not allowed because of missing messages
+ const {user,member,channel,guild} = instance
+ const generalConfig = opendiscord.configs.get("opendiscord:general")
+ const lang = opendiscord.languages
+ 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 (!guild || channel.isDMBased()) throw new api.ODSystemError("replyMessageMustBeSentBeforeClose() must be used in a guild and not a DM channel.")
+
+ if (!permsResult.isAdmin && (!generalConfig.data.ticketSystem.allowCloseBeforeMessage || !generalConfig.data.ticketSystem.allowCloseBeforeAdminMessage)){
+ const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
+ 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")}))
+ return false
+ }
+ 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")}))
+ return false
+ }
+ return true
+ }else return true
+}
+
+/**Update the ticket message from a given ticket channel. This should be used after every change to the `ODTicket` after an action. */
+export async function updateTicketMessage(guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:api.ODTicket){
+ const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
+ if (!ticketMessage || !user || !channel || !guild || channel.isDMBased()) return
+ try{
+ await ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
+ }catch(e){
+ opendiscord.log("Unable to edit ticket message!","error",[
+ {key:"channel",value:"#"+channel.name},
+ {key:"channelid",value:channel.id,hidden:true},
+ {key:"messageid",value:ticketMessage.id},
+ {key:"option",value:ticket.option.id.value}
+ ])
+ opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
+ }
+}
\ No newline at end of file
diff --git a/src/builders/buttons.ts b/src/builders/buttons.ts
index cc9cba9..b4ae6cd 100644
--- a/src/builders/buttons.ts
+++ b/src/builders/buttons.ts
@@ -1,15 +1,37 @@
///////////////////////////////////////
//BUTTON BUILDERS
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const buttons = opendiscord.builders.buttons
const lang = opendiscord.languages
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerAllButtons = async () => {
- verifybarButtons()
+export async function registerAllButtons(){
+ //VERIFYBAR BUTTON
+ buttons.add(new api.ODButton("opendiscord:verifybar-button"))
+ buttons.get("opendiscord:verifybar-button").workers.add(
+ new api.ODWorker("opendiscord:verifybar-button",0,async (instance,params) => {
+ const {verifybar,verifyButtonId} = params
+ if (params.verifyButtonId.length > 40) throw new api.ODSystemError("ODButton:opendiscord:verifybar-button => verifyButtonId '"+verifyButtonId+"' exceeds 40 characters limit!")
+
+ const color = ("customColor" in params && params.customColor) ? params.customColor : "gray"
+ //TODO TRANSLATION!!!
+ const defaultLabel = (params.defaultButtonType == "โ
") ? "Accept" : "Cancel"
+ const defaultEmoji = (params.defaultButtonType == "โ
") ? "โ
" : "โ"
+
+ const label = ("customLabel" in params && params.customLabel) ? params.customLabel : (params.useDefaultLabels ? defaultLabel : null)
+ const emoji = ("customEmoji" in params && params.customEmoji) ? params.customEmoji : defaultEmoji
+
+ instance.setCustomId("od:verifybar|"+verifybar.id.value+"|"+verifyButtonId)
+ instance.setMode("button")
+ instance.setColor(color)
+ if (label) instance.setLabel(label)
+ if (emoji) instance.setEmoji(emoji)
+ })
+ )
+
errorButtons()
helpMenuButtons()
panelButtons()
@@ -18,50 +40,6 @@ export const registerAllButtons = async () => {
clearButtons()
}
-const verifybarButtons = () => {
- //VERIFYBAR SUCCESS
- buttons.add(new api.ODButton("opendiscord:verifybar-success"))
- buttons.get("opendiscord:verifybar-success").workers.add(
- new api.ODWorker("opendiscord:verifybar-success",0,async (instance,params) => {
- const {verifybar,customData,customColor,customLabel,customEmoji} = params
-
- if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:opendiscord:verifybar-success => customData exceeds 40 characters limit!")
-
- const newData = (customData) ? "_"+customData : ""
- const newColor = customColor ?? "gray"
- const newLabel = customLabel ?? ""
- const newEmoji = customEmoji ?? "โ
"
-
- instance.setCustomId("od:verifybar-success_"+verifybar.id.value+newData)
- instance.setMode("button")
- instance.setColor(newColor)
- if (newLabel) instance.setLabel(newLabel)
- if (newEmoji) instance.setEmoji(newEmoji)
- })
- )
-
- //VERIFYBAR FAILURE
- buttons.add(new api.ODButton("opendiscord:verifybar-failure"))
- buttons.get("opendiscord:verifybar-failure").workers.add(
- new api.ODWorker("opendiscord:verifybar-failure",0,async (instance,params) => {
- const {verifybar,customData,customColor,customLabel,customEmoji} = params
-
- if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:opendiscord:verifybar-success => customData exceeds 40 characters limit!")
-
- const newData = (customData) ? "_"+customData : ""
- const newColor = customColor ?? "gray"
- const newLabel = customLabel ?? ""
- const newEmoji = customEmoji ?? "โ"
-
- instance.setCustomId("od:verifybar-failure_"+verifybar.id.value+newData)
- instance.setMode("button")
- instance.setColor(newColor)
- if (newLabel) instance.setLabel(newLabel)
- if (newEmoji) instance.setEmoji(newEmoji)
- })
- )
-}
-
const errorButtons = () => {
//ERROR TICKET DEPRECATED TRANSCRIPT
buttons.add(new api.ODButton("opendiscord:error-ticket-deprecated-transcript"))
@@ -201,11 +179,11 @@ const ticketButtons = () => {
//CLOSE TICKET
buttons.add(new api.ODButton("opendiscord:close-ticket"))
buttons.get("opendiscord:close-ticket").workers.add(
- new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
- instance.setCustomId("od:close-ticket_"+source)
+ instance.setCustomId("od:close-ticket")
instance.setColor("gray")
instance.setEmoji("๐")
instance.setLabel(lang.getTranslation("actions.buttons.close"))
@@ -215,11 +193,11 @@ const ticketButtons = () => {
//DELETE TICKET
buttons.add(new api.ODButton("opendiscord:delete-ticket"))
buttons.get("opendiscord:delete-ticket").workers.add(
- new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
- instance.setCustomId("od:delete-ticket_"+source)
+ instance.setCustomId("od:delete-ticket")
instance.setColor("red")
instance.setEmoji("โ")
instance.setLabel(lang.getTranslation("actions.buttons.delete"))
@@ -229,11 +207,11 @@ const ticketButtons = () => {
//REOPEN TICKET
buttons.add(new api.ODButton("opendiscord:reopen-ticket"))
buttons.get("opendiscord:reopen-ticket").workers.add(
- new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
- instance.setCustomId("od:reopen-ticket_"+source)
+ instance.setCustomId("od:reopen-ticket")
instance.setColor("green")
instance.setEmoji("๐")
instance.setLabel(lang.getTranslation("actions.buttons.reopen"))
@@ -243,11 +221,11 @@ const ticketButtons = () => {
//CLAIM TICKET
buttons.add(new api.ODButton("opendiscord:claim-ticket"))
buttons.get("opendiscord:claim-ticket").workers.add(
- new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
- instance.setCustomId("od:claim-ticket_"+source)
+ instance.setCustomId("od:claim-ticket")
instance.setColor("green")
instance.setEmoji("๐")
instance.setLabel(lang.getTranslation("actions.buttons.claim"))
@@ -257,11 +235,11 @@ const ticketButtons = () => {
//UNCLAIM TICKET
buttons.add(new api.ODButton("opendiscord:unclaim-ticket"))
buttons.get("opendiscord:unclaim-ticket").workers.add(
- new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
- instance.setCustomId("od:unclaim-ticket_"+source)
+ instance.setCustomId("od:unclaim-ticket")
instance.setColor("green")
instance.setEmoji("โฉ๏ธ")
instance.setLabel(lang.getTranslation("actions.buttons.unclaim"))
@@ -271,13 +249,13 @@ const ticketButtons = () => {
//PIN TICKET
buttons.add(new api.ODButton("opendiscord:pin-ticket"))
buttons.get("opendiscord:pin-ticket").workers.add(
- new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
- instance.setCustomId("od:pin-ticket_"+source)
+ instance.setCustomId("od:pin-ticket")
instance.setColor("gray")
- instance.setEmoji(generalConfig.data.system.pinEmoji)
+ instance.setEmoji(generalConfig.data.ticketSystem.pinEmoji)
instance.setLabel(lang.getTranslation("actions.buttons.pin"))
})
)
@@ -285,13 +263,13 @@ const ticketButtons = () => {
//UNPIN TICKET
buttons.add(new api.ODButton("opendiscord:unpin-ticket"))
buttons.get("opendiscord:unpin-ticket").workers.add(
- new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
- instance.setCustomId("od:unpin-ticket_"+source)
+ instance.setCustomId("od:unpin-ticket")
instance.setColor("gray")
- instance.setEmoji(generalConfig.data.system.pinEmoji)
+ instance.setEmoji(generalConfig.data.ticketSystem.pinEmoji)
instance.setLabel(lang.getTranslation("actions.buttons.unpin"))
})
)
@@ -301,7 +279,7 @@ const transcriptButtons = () => {
//TRANSCRIPT HTML VISIT
buttons.add(new api.ODButton("opendiscord:transcript-html-visit"))
buttons.get("opendiscord:transcript-html-visit").workers.add(
- new api.ODWorker("opendiscord:transcript-html-visit",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-html-visit",0,async (instance,params,origin) => {
const {result} = params
instance.setMode("url")
if (result.data) instance.setUrl(result.data.url)
@@ -314,9 +292,9 @@ const transcriptButtons = () => {
//TRANSCRIPT ERROR RETRY
buttons.add(new api.ODButton("opendiscord:transcript-error-retry"))
buttons.get("opendiscord:transcript-error-retry").workers.add(
- new api.ODWorker("opendiscord:transcript-error-retry",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-error-retry",0,async (instance,params,origin) => {
instance.setMode("button")
- instance.setCustomId("od:transcript-error-retry_"+source)
+ instance.setCustomId("od:transcript-error-retry_"+origin)
instance.setColor("gray")
instance.setEmoji("๐")
instance.setLabel(lang.getTranslation("transcripts.errors.retry"))
@@ -326,9 +304,9 @@ const transcriptButtons = () => {
//TRANSCRIPT ERROR CONTINUE
buttons.add(new api.ODButton("opendiscord:transcript-error-continue"))
buttons.get("opendiscord:transcript-error-continue").workers.add(
- new api.ODWorker("opendiscord:transcript-error-continue",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-error-continue",0,async (instance,params,origin) => {
instance.setMode("button")
- instance.setCustomId("od:transcript-error-continue_"+source)
+ instance.setCustomId("od:transcript-error-continue_"+origin)
instance.setColor("red")
instance.setEmoji("โ")
instance.setLabel(lang.getTranslation("transcripts.errors.continue"))
@@ -340,12 +318,13 @@ const clearButtons = () => {
//CLEAR CONTINUE
buttons.add(new api.ODButton("opendiscord:clear-continue"))
buttons.get("opendiscord:clear-continue").workers.add(
- new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,origin) => {
instance.setMode("button")
- instance.setCustomId("od:clear-continue_"+source+"_"+params.filter)
+ instance.setCustomId("od:clear-continue")
instance.setColor("red")
instance.setEmoji("โ")
instance.setLabel(lang.getTranslation("actions.buttons.clear"))
+ instance.setDisabled(params.inProgress)
})
)
}
\ No newline at end of file
diff --git a/src/builders/dropdowns.ts b/src/builders/dropdowns.ts
index 2f675c5..c83ebd7 100644
--- a/src/builders/dropdowns.ts
+++ b/src/builders/dropdowns.ts
@@ -1,12 +1,12 @@
///////////////////////////////////////
//DROPDOWN BUILDERS
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const dropdowns = opendiscord.builders.dropdowns
-export const registerAllDropdowns = async () => {
+export async function registerAllDropdowns(){
panelDropdowns()
}
diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts
index 5d7cc2c..c8e7f7e 100644
--- a/src/builders/embeds.ts
+++ b/src/builders/embeds.ts
@@ -1,7 +1,7 @@
///////////////////////////////////////
//EMBED BUILDERS
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
import nodepath from "path"
@@ -9,7 +9,7 @@ const embeds = opendiscord.builders.embeds
const lang = opendiscord.languages
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerAllEmbeds = async () => {
+export async function registerAllEmbeds(){
errorEmbeds()
helpMenuEmbeds()
statsEmbeds()
@@ -23,12 +23,12 @@ export const registerAllEmbeds = async () => {
extraEmbeds()
}
-/**Utility function to get the translated "method" from the source. Mostly used in error embeds. */
-const getMethodFromSource = (source:"slash"|"text"|"button"|"dropdown"|"modal"|"other"): string => {
- if (source == "slash" || source == "text") return lang.getTranslation("params.lowercase.command")
- else if (source == "button") return lang.getTranslation("params.lowercase.button")
- else if (source == "dropdown") return lang.getTranslation("params.lowercase.dropdown")
- else if (source == "modal") return lang.getTranslation("params.lowercase.modal")
+/**Utility function to get the translated "method" from the origin. Mostly used in error embeds. */
+const getMethodFromOrigin = (origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other"): string => {
+ if (origin == "slash" || origin == "text") return lang.getTranslation("params.lowercase.command")
+ else if (origin == "button") return lang.getTranslation("params.lowercase.button")
+ else if (origin == "dropdown") return lang.getTranslation("params.lowercase.dropdown")
+ else if (origin == "modal") return lang.getTranslation("params.lowercase.modal")
else return lang.getTranslation("params.lowercase.method")
}
//lang.getTranslation()
@@ -37,12 +37,12 @@ const errorEmbeds = () => {
//ERROR
embeds.add(new api.ODEmbed("opendiscord:error"))
embeds.get("opendiscord:error").workers.add(
- new api.ODWorker("opendiscord:error",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error",0,async (instance,params,origin) => {
const {user,error,layout,customTitle} = params
- const method = getMethodFromSource(source)
+ 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.setAuthor(user.displayName,user.displayAvatarURL())
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(" ")+"**"
- 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.setAuthor(user.displayName,user.displayAvatarURL())
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 == "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.setAuthor(user.displayName,user.displayAvatarURL())
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) => {
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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.unknownCommand"))
@@ -154,10 +154,10 @@ const errorEmbeds = () => {
//ERROR NO PERMISSIONS
embeds.add(new api.ODEmbed("opendiscord:error-no-permissions"))
embeds.get("opendiscord:error-no-permissions").workers.add(
- new api.ODWorker("opendiscord:error-no-permissions",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-no-permissions",0,async (instance,params,origin) => {
const {user,permissions} = params
- const method = getMethodFromSource(source)
+ const method = getMethodFromOrigin(origin)
const renderedPerms = permissions.map((perm) => {
if (perm == "developer") return "- "+lang.getTranslation("errors.permissions.developer")
@@ -169,7 +169,7 @@ const errorEmbeds = () => {
else if (perm == "discord-administrator") return "- "+lang.getTranslation("errors.permissions.discord-administrator")
}).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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissions",[method]))
@@ -180,12 +180,12 @@ const errorEmbeds = () => {
//ERROR NO PERMISSIONS COOLDOWN
embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-cooldown"))
embeds.get("opendiscord:error-no-permissions-cooldown").workers.add(
- new api.ODWorker("opendiscord:error-no-permissions-cooldown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-no-permissions-cooldown",0,async (instance,params,origin) => {
const {user} = params
- const method = getMethodFromSource(source)
+ 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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsCooldown",[method]))
@@ -196,12 +196,12 @@ const errorEmbeds = () => {
//ERROR NO PERMISSIONS BLACKLISTED
embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-blacklisted"))
embeds.get("opendiscord:error-no-permissions-blacklisted").workers.add(
- new api.ODWorker("opendiscord:error-no-permissions-blacklisted",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-no-permissions-blacklisted",0,async (instance,params,origin) => {
const {user} = params
- const method = getMethodFromSource(source)
+ 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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsBlacklist",[method]))
@@ -211,10 +211,10 @@ const errorEmbeds = () => {
//ERROR NO PERMISSIONS LIMITS
embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-limits"))
embeds.get("opendiscord:error-no-permissions-limits").workers.add(
- new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,origin) => {
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.setAuthor(user.displayName,user.displayAvatarURL())
if (limit == "global") instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsLimitGlobal"))
@@ -227,12 +227,12 @@ const errorEmbeds = () => {
//ERROR RESPONDER TIMEOUT
embeds.add(new api.ODEmbed("opendiscord:error-responder-timeout"))
embeds.get("opendiscord:error-responder-timeout").workers.add(
- new api.ODWorker("opendiscord:error-responder-timeout",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-responder-timeout",0,async (instance,params,origin) => {
const {user} = params
- const method = getMethodFromSource(source)
+ 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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method]))
@@ -244,10 +244,10 @@ const errorEmbeds = () => {
//ERROR TICKET UNKNOWN
embeds.add(new api.ODEmbed("opendiscord:error-ticket-unknown"))
embeds.get("opendiscord:error-ticket-unknown").workers.add(
- new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,origin) => {
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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.unknownTicket"))
@@ -258,10 +258,10 @@ const errorEmbeds = () => {
//ERROR TICKET DEPRECATED
embeds.add(new api.ODEmbed("opendiscord:error-ticket-deprecated"))
embeds.get("opendiscord:error-ticket-deprecated").workers.add(
- new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,origin) => {
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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.deprecatedTicket"))
@@ -272,7 +272,7 @@ const errorEmbeds = () => {
//ERROR OPTION UNKNOWN
embeds.add(new api.ODEmbed("opendiscord:error-option-unknown"))
embeds.get("opendiscord:error-option-unknown").workers.add(
- new api.ODWorker("opendiscord:error-option-unknown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-option-unknown",0,async (instance,params,origin) => {
const {user} = params
const renderedTicketOptions = opendiscord.options.getAll().map((option) => {
@@ -281,7 +281,7 @@ const errorEmbeds = () => {
}else return "- `"+option.id.value+"`"
}).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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo"))
@@ -292,7 +292,7 @@ const errorEmbeds = () => {
//ERROR PANEL UNKNOWN
embeds.add(new api.ODEmbed("opendiscord:error-panel-unknown"))
embeds.get("opendiscord:error-panel-unknown").workers.add(
- new api.ODWorker("opendiscord:error-panel-unknown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-panel-unknown",0,async (instance,params,origin) => {
const {user} = params
const renderedPanels = opendiscord.panels.getAll().map((panel) => {
@@ -301,7 +301,7 @@ const errorEmbeds = () => {
}else return "- `"+panel.id.value+"`"
}).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.setAuthor(user.displayName,user.displayAvatarURL())
instance.addFields({name:lang.getTranslation("params.uppercase.validPanels")+":",value:renderedPanels})
@@ -312,12 +312,12 @@ const errorEmbeds = () => {
//ERROR NOT IN GUILD
embeds.add(new api.ODEmbed("opendiscord:error-not-in-guild"))
embeds.get("opendiscord:error-not-in-guild").workers.add(
- new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,origin) => {
const {user} = params
- const method = getMethodFromSource(source)
+ 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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.notInGuild",[method]))
@@ -327,19 +327,43 @@ const errorEmbeds = () => {
//ERROR CHANNEL RENAME
embeds.add(new api.ODEmbed("opendiscord:error-channel-rename"))
embeds.get("opendiscord:error-channel-rename").workers.add(
- new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,origin) => {
const {channel,user,originalName,newName} = params
- const method = (source == "ticket-move" || source == "ticket-pin" || source == "ticket-rename" || source == "ticket-unpin" || source == "ticket-priority" || source == "ticket-transfer") ? source : getMethodFromSource(source)
+ 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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.channelRename"))
instance.setFooter(lang.getTranslationWithParams("errors.descriptions.channelRenameSource",[method]))
instance.addFields(
- {name:lang.getTranslation("params.uppercase.originalName")+":",value:"```#"+originalName+"```",inline:false},
- {name:lang.getTranslation("params.uppercase.newName")+":",value:"```#"+newName+"```",inline:false}
+ {name:lang.getTranslation("params.uppercase.originalName")+":",value:"```#"+originalName+"```",inline:true},
+ {name:lang.getTranslation("params.uppercase.newName")+":",value:"```#"+newName+"```",inline:true}
+ )
+ })
+ )
+
+ //ERROR CHANNEL CATEGORY
+ embeds.add(new api.ODEmbed("opendiscord:error-channel-category"))
+ embeds.get("opendiscord:error-channel-category").workers.add(
+ new api.ODWorker("opendiscord:error-channel-category",0,async (instance,params,origin) => {
+ const {channel,user,originalCategory,newCategory} = params
+
+ 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.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
+ //TODO TRANSLATION!!!
+ instance.setTitle(utilities.emojiTitle("โ","Unable To Change Category"))
+ instance.setAuthor(user.displayName,user.displayAvatarURL())
+ //TODO TRANSLATION!!!
+ instance.setDescription("Due to Discord rate limits, the channel category could not be changed immediately. It will be changed automatically within 10 minutes if the bot remains online.")
+ instance.setFooter(lang.getTranslationWithParams("errors.descriptions.channelRenameSource",[method]))
+ instance.addFields(
+ //TODO TRANSLATION!!!
+ {name:"Original Category"+":",value:"```"+originalCategory+"```",inline:true},
+ //TODO TRANSLATION!!!
+ {name:"New Category"+":",value:"```"+newCategory+"```",inline:true}
)
})
)
@@ -347,12 +371,12 @@ const errorEmbeds = () => {
//ERROR TICKET BUSY
embeds.add(new api.ODEmbed("opendiscord:error-ticket-busy"))
embeds.get("opendiscord:error-ticket-busy").workers.add(
- new api.ODWorker("opendiscord:error-ticket-busy",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-ticket-busy",0,async (instance,params,origin) => {
const {user} = params
- const method = getMethodFromSource(source)
+ 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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.busy",[method]))
@@ -387,7 +411,7 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-global",0,async (instance,params) => {
const {guild,channel,user} = params
- const scope = opendiscord.stats.get("opendiscord:global")
+ const scope = opendiscord.statistics.get("opendiscord:global")
if (!scope) return
const data = await scope.render("GLOBAL",guild,channel,user)
@@ -397,7 +421,7 @@ const statsEmbeds = () => {
if (opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(user,channel,guild))){
//show system data when owner or developer
- const systemScope = opendiscord.stats.get("opendiscord:system")
+ const systemScope = opendiscord.statistics.get("opendiscord:system")
if (!systemScope) return
const systemData = await systemScope.render("GLOBAL",guild,channel,user)
instance.addFields({name:systemScope.name,value:systemData,inline:false})
@@ -411,9 +435,9 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-ticket",0,async (instance,params) => {
const {guild,channel,user,scopeData} = params
- const scope = opendiscord.stats.get("opendiscord:ticket")
- const participantsScope = opendiscord.stats.get("opendiscord:participants")
- const messagesScope = opendiscord.stats.get("opendiscord:messages")
+ const scope = opendiscord.statistics.get("opendiscord:ticket")
+ const participantsScope = opendiscord.statistics.get("opendiscord:participants")
+ const messagesScope = opendiscord.statistics.get("opendiscord:messages")
if (!scope || !participantsScope || !messagesScope) return
const data = await scope.render(scopeData.id.value,guild,channel,user)
const participantsData = await participantsScope.render(scopeData.id.value,guild,channel,user)
@@ -433,7 +457,7 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-user",0,async (instance,params) => {
const {guild,channel,user,scopeData} = params
- const scope = opendiscord.stats.get("opendiscord:user")
+ const scope = opendiscord.statistics.get("opendiscord:user")
if (!scope) return
const data = await scope.render(scopeData.id,guild,channel,user)
@@ -477,7 +501,7 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-ticket-unknown",0,async (instance,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.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.statsError",[discord.channelMention(id)]))
@@ -510,8 +534,8 @@ const panelEmbeds = () => {
instance.setDescription(embedOptions.description)
}
- if (panel.get("opendiscord:enable-max-tickets-warning-embed").value && generalConfig.data.system.limits.enabled){
- instance.setDescription(instance.data.description+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*")
+ 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.ticketSystem.limits.userMaximum.toString()])+"*")
}
if (panel.get("opendiscord:describe-options-in-embed-fields").value){
@@ -529,7 +553,7 @@ const ticketEmbeds = () => {
//TICKET CREATED
embeds.add(new api.ODEmbed("opendiscord:ticket-created"))
embeds.get("opendiscord:ticket-created").workers.add(
- new api.ODWorker("opendiscord:ticket-created",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-created",0,async (instance,params,origin) => {
const {user} = params
instance.setColor(generalConfig.data.mainColor)
@@ -543,7 +567,7 @@ const ticketEmbeds = () => {
//TICKET CREATED DM
embeds.add(new api.ODEmbed("opendiscord:ticket-created-dm"))
embeds.get("opendiscord:ticket-created-dm").workers.add(
- new api.ODWorker("opendiscord:ticket-created-dm",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-created-dm",0,async (instance,params,origin) => {
const {user,ticket} = params
const embedOptions = ticket.option.get("opendiscord:dm-message-embed").value
@@ -563,10 +587,10 @@ const ticketEmbeds = () => {
//TICKET CREATED LOGS
embeds.add(new api.ODEmbed("opendiscord:ticket-created-logs"))
embeds.get("opendiscord:ticket-created-logs").workers.add(
- new api.ODWorker("opendiscord:ticket-created-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-created-logs",0,async (instance,params,origin) => {
const {user,ticket} = params
- const method = (source == "panel-button" || source == "panel-dropdown") ? lang.getTranslation("params.uppercase.panel") : (source == "slash" || source == "text") ? lang.getTranslation("params.uppercase.command") : lang.getTranslation("params.uppercase.system")
+ const method = (origin == "panel-button" || origin == "panel-dropdown") ? lang.getTranslation("params.uppercase.panel") : (origin == "slash" || origin == "text") ? lang.getTranslation("params.uppercase.command") : lang.getTranslation("params.uppercase.system")
const blacklisted = opendiscord.blacklist.exists(user.id) ? lang.getTranslation("params.uppercase.true") : lang.getTranslation("params.uppercase.false")
instance.setColor(generalConfig.data.mainColor)
@@ -586,7 +610,7 @@ const ticketEmbeds = () => {
//TICKET MESSAGE
embeds.add(new api.ODEmbed("opendiscord:ticket-message"))
embeds.get("opendiscord:ticket-message").workers.add(
- new api.ODWorker("opendiscord:ticket-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-message",0,async (instance,params,origin) => {
const {user,ticket} = params
const embedOptions = ticket.option.get("opendiscord:ticket-message-embed").value
@@ -599,12 +623,12 @@ const ticketEmbeds = () => {
if (ticket.option.get("opendiscord:questions").value.length > 0){
//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
answers.forEach((answer) => {
if (!answer.value || answer.value.length == 0) return
- if (generalConfig.data.system.questionFieldsInCodeBlock) instance.addFields({name:answer.name,value:"```"+answer.value+"```",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 if (embedOptions.fields){
@@ -625,161 +649,161 @@ const ticketEmbeds = () => {
//TICKET CLOSED
embeds.add(new api.ODEmbed("opendiscord:close-message"))
embeds.get("opendiscord:close-message").workers.add(
- new api.ODWorker("opendiscord:close-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:close-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.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 ?? "/")+"```"})
})
)
//TICKET REOPENED
embeds.add(new api.ODEmbed("opendiscord:reopen-message"))
embeds.get("opendiscord:reopen-message").workers.add(
- new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.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 ?? "/")+"```"})
})
)
//TICKET DELETED
embeds.add(new api.ODEmbed("opendiscord:delete-message"))
embeds.get("opendiscord:delete-message").workers.add(
- new api.ODWorker("opendiscord:delete-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:delete-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐๏ธ",lang.getTranslation("actions.titles.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 ?? "/")+"```"})
})
)
//TICKET CLAIMED
embeds.add(new api.ODEmbed("opendiscord:claim-message"))
embeds.get("opendiscord:claim-message").workers.add(
- new api.ODWorker("opendiscord:claim-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:claim-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.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 ?? "/")+"```"})
})
)
//TICKET UNCLAIMED
embeds.add(new api.ODEmbed("opendiscord:unclaim-message"))
embeds.get("opendiscord:unclaim-message").workers.add(
- new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("โฉ๏ธ",lang.getTranslation("actions.titles.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 ?? "/")+"```"})
})
)
//TICKET PINNED
embeds.add(new api.ODEmbed("opendiscord:pin-message"))
embeds.get("opendiscord:pin-message").workers.add(
- new api.ODWorker("opendiscord:pin-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:pin-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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"))
- 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 ?? "/")+"```"})
})
)
//TICKET UNPINNED
embeds.add(new api.ODEmbed("opendiscord:unpin-message"))
embeds.get("opendiscord:unpin-message").workers.add(
- new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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"))
- 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 ?? "/")+"```"})
})
)
//TICKET RENAMED
embeds.add(new api.ODEmbed("opendiscord:rename-message"))
embeds.get("opendiscord:rename-message").workers.add(
- new api.ODWorker("opendiscord:rename-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:rename-message",0,async (instance,params,origin) => {
const {user,ticket,reason,data} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.rename")))
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 ?? "/")+"```"})
})
)
//TICKET MOVED
embeds.add(new api.ODEmbed("opendiscord:move-message"))
embeds.get("opendiscord:move-message").workers.add(
- new api.ODWorker("opendiscord:move-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:move-message",0,async (instance,params,origin) => {
const {user,ticket,reason,data} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.move")))
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 ?? "/")+"```"})
})
)
//TICKET USER ADDED
embeds.add(new api.ODEmbed("opendiscord:add-message"))
embeds.get("opendiscord:add-message").workers.add(
- new api.ODWorker("opendiscord:add-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:add-message",0,async (instance,params,origin) => {
const {user,ticket,reason,data} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐ค",lang.getTranslation("actions.titles.add")))
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 ?? "/")+"```"})
})
)
//TICKET USER REMOVED
embeds.add(new api.ODEmbed("opendiscord:remove-message"))
embeds.get("opendiscord:remove-message").workers.add(
- new api.ODWorker("opendiscord:remove-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:remove-message",0,async (instance,params,origin) => {
const {user,ticket,reason,data} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐ค",lang.getTranslation("actions.titles.remove")))
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 ?? "/")+"```"})
})
)
//TICKET ACTION DM
embeds.add(new api.ODEmbed("opendiscord:ticket-action-dm"))
embeds.get("opendiscord:ticket-action-dm").workers.add(
- new api.ODWorker("opendiscord:ticket-action-dm",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-action-dm",0,async (instance,params,origin) => {
const {user,mode,ticket,reason,additionalData} = params
const channel = await opendiscord.tickets.getTicketChannel(ticket)
@@ -804,10 +828,10 @@ const ticketEmbeds = () => {
instance.setTitle(utilities.emojiTitle("โฉ๏ธ",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslation("actions.logs.unclaimDm"))
}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"))
}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"))
}else if (mode == "rename"){
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.rename")))
@@ -828,7 +852,7 @@ const ticketEmbeds = () => {
//TICKET ACTION LOGS
embeds.add(new api.ODEmbed("opendiscord:ticket-action-logs"))
embeds.get("opendiscord:ticket-action-logs").workers.add(
- new api.ODWorker("opendiscord:ticket-action-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-action-logs",0,async (instance,params,origin) => {
const {user,mode,ticket,reason,additionalData} = params
const channel = await opendiscord.tickets.getTicketChannel(ticket)
@@ -840,7 +864,7 @@ const ticketEmbeds = () => {
{name:lang.getTranslation("params.uppercase.ticket")+":",value:"```#"+(channel ? channel.name : "")+"```",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"){
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.close")))
@@ -858,10 +882,10 @@ const ticketEmbeds = () => {
instance.setTitle(utilities.emojiTitle("โฉ๏ธ",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslationWithParams("actions.logs.unclaimLog",[discord.userMention(user.id)]))
}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)]))
}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)]))
}else if (mode == "rename"){
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.rename")))
@@ -884,7 +908,7 @@ const blacklistEmbeds = () => {
//BLACKLIST VIEW
embeds.add(new api.ODEmbed("opendiscord:blacklist-view"))
embeds.get("opendiscord:blacklist-view").workers.add(
- new api.ODWorker("opendiscord:blacklist-view",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-view",0,async (instance,params,origin) => {
const {user} = params
const renderedUsers: string[] = []
@@ -904,7 +928,7 @@ const blacklistEmbeds = () => {
//BLACKLIST GET
embeds.add(new api.ODEmbed("opendiscord:blacklist-get"))
embeds.get("opendiscord:blacklist-get").workers.add(
- new api.ODWorker("opendiscord:blacklist-get",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-get",0,async (instance,params,origin) => {
const {user,data} = params
const blacklist = opendiscord.blacklist.get(data.id)
@@ -914,7 +938,7 @@ const blacklistEmbeds = () => {
if (blacklist){
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)])+"*")
})
@@ -923,35 +947,35 @@ const blacklistEmbeds = () => {
//BLACKLIST ADD
embeds.add(new api.ODEmbed("opendiscord:blacklist-add"))
embeds.get("opendiscord:blacklist-add").workers.add(
- new api.ODWorker("opendiscord:blacklist-add",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-add",0,async (instance,params,origin) => {
const {user,data,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐ซ",lang.getTranslation("actions.titles.blacklistAdd")))
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 ?? "/")+"```"})
})
)
//BLACKLIST REMOVE
embeds.add(new api.ODEmbed("opendiscord:blacklist-remove"))
embeds.get("opendiscord:blacklist-remove").workers.add(
- new api.ODWorker("opendiscord:blacklist-remove",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-remove",0,async (instance,params,origin) => {
const {user,data,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐",lang.getTranslation("actions.titles.blacklistRemove")))
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 ?? "/")+"```"})
})
)
//BLACKLIST DM
embeds.add(new api.ODEmbed("opendiscord:blacklist-dm"))
embeds.get("opendiscord:blacklist-dm").workers.add(
- new api.ODWorker("opendiscord:blacklist-dm",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-dm",0,async (instance,params,origin) => {
const {user,mode,data,reason} = params
const title = (mode == "add") ? lang.getTranslation("actions.titles.blacklistAddDm") : lang.getTranslation("actions.titles.blacklistRemoveDm")
@@ -961,14 +985,14 @@ const blacklistEmbeds = () => {
instance.setTitle(utilities.emojiTitle((mode == "add") ? "๐ซ" : "๐",title))
instance.setTimestamp(new Date())
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 ?? "/")+"```"})
})
)
//BLACKLIST LOGS
embeds.add(new api.ODEmbed("opendiscord:blacklist-logs"))
embeds.get("opendiscord:blacklist-logs").workers.add(
- new api.ODWorker("opendiscord:blacklist-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-logs",0,async (instance,params,origin) => {
const {user,mode,data,reason} = params
const title = (mode == "add") ? lang.getTranslation("actions.titles.blacklistAdd") : lang.getTranslation("actions.titles.blacklistRemove")
@@ -980,7 +1004,7 @@ const blacklistEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setTimestamp(new Date())
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 ?? "/")+"```"})
})
)
}
@@ -989,7 +1013,7 @@ const transcriptEmbeds = () => {
//TRANSCRIPT TEXT READY
embeds.add(new api.ODEmbed("opendiscord:transcript-text-ready"))
embeds.get("opendiscord:transcript-text-ready").workers.add(
- new api.ODWorker("opendiscord:transcript-text-ready",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-text-ready",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler} = params
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
@@ -1007,11 +1031,11 @@ const transcriptEmbeds = () => {
}catch{}
}
- if (source == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.text")]))
- else if (source == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.text")]))
- else if (source == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.text")]))
- else if (source == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.text")]))
- else if (source == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.text")]))
+ if (origin == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.text")]))
+ else if (origin == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.text")]))
+ else if (origin == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.text")]))
+ else if (origin == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.text")]))
+ else if (origin == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.text")]))
else instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdOther",[lang.getTranslation("params.lowercase.text")]))
})
)
@@ -1019,7 +1043,7 @@ const transcriptEmbeds = () => {
//TRANSCRIPT HTML READY
embeds.add(new api.ODEmbed("opendiscord:transcript-html-ready"))
embeds.get("opendiscord:transcript-html-ready").workers.add(
- new api.ODWorker("opendiscord:transcript-html-ready",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-html-ready",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,result} = params
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
@@ -1038,11 +1062,11 @@ const transcriptEmbeds = () => {
}catch{}
}
- if (source == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.html")]))
- else if (source == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.html")]))
- else if (source == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.html")]))
- else if (source == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.html")]))
- else if (source == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.html")]))
+ if (origin == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.html")]))
+ else if (origin == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.html")]))
+ else if (origin == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.html")]))
+ else if (origin == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.html")]))
+ else if (origin == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.html")]))
else instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdOther",[lang.getTranslation("params.lowercase.html")]))
})
)
@@ -1050,7 +1074,7 @@ const transcriptEmbeds = () => {
//TRANSCRIPT HTML PROGRESS
embeds.add(new api.ODEmbed("opendiscord:transcript-html-progress"))
embeds.get("opendiscord:transcript-html-progress").workers.add(
- new api.ODWorker("opendiscord:transcript-html-progress",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-html-progress",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,remaining} = params
const remainingDate = new Date(new Date().getTime()+remaining)
@@ -1076,15 +1100,15 @@ const transcriptEmbeds = () => {
//TRANSCRIPT ERROR
embeds.add(new api.ODEmbed("opendiscord:transcript-error"))
embeds.get("opendiscord:transcript-error").workers.add(
- new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,origin) => {
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.setTimestamp(new Date())
instance.setDescription(lang.getTranslation("transcripts.errors.error"))
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 ?? "/")+"```"})
})
)
}
@@ -1093,7 +1117,7 @@ const roleEmbeds = () => {
//REACTION ROLE
embeds.add(new api.ODEmbed("opendiscord:reaction-role"))
embeds.get("opendiscord:reaction-role").workers.add(
- new api.ODWorker("opendiscord:reaction-role",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reaction-role",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1117,7 +1141,7 @@ const roleEmbeds = () => {
//REACTION ROLE DM
embeds.add(new api.ODEmbed("opendiscord:reaction-role-dm"))
embeds.get("opendiscord:reaction-role-dm").workers.add(
- new api.ODWorker("opendiscord:reaction-role-dm",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reaction-role-dm",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1143,7 +1167,7 @@ const roleEmbeds = () => {
//REACTION ROLE LOGS
embeds.add(new api.ODEmbed("opendiscord:reaction-role-logs"))
embeds.get("opendiscord:reaction-role-logs").workers.add(
- new api.ODWorker("opendiscord:reaction-role-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reaction-role-logs",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1171,7 +1195,7 @@ const clearEmbeds = () => {
//CLEAR VERIFY MESSAGE
embeds.add(new api.ODEmbed("opendiscord:clear-verify-message"))
embeds.get("opendiscord:clear-verify-message").workers.add(
- new api.ODWorker("opendiscord:clear-verify-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:clear-verify-message",0,async (instance,params,origin) => {
const {guild,channel,user,filter,list} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1189,7 +1213,7 @@ const clearEmbeds = () => {
//CLEAR MESSAGE
embeds.add(new api.ODEmbed("opendiscord:clear-message"))
embeds.get("opendiscord:clear-message").workers.add(
- new api.ODWorker("opendiscord:clear-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:clear-message",0,async (instance,params,origin) => {
const {guild,channel,user,filter,list} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1206,7 +1230,7 @@ const clearEmbeds = () => {
//CLEAR LOGS
embeds.add(new api.ODEmbed("opendiscord:clear-logs"))
embeds.get("opendiscord:clear-logs").workers.add(
- new api.ODWorker("opendiscord:clear-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:clear-logs",0,async (instance,params,origin) => {
const {guild,channel,user,filter,list} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1226,10 +1250,10 @@ const autoEmbeds = () => {
//AUTOCLOSE MESSAGE
embeds.add(new api.ODEmbed("opendiscord:autoclose-message"))
embeds.get("opendiscord:autoclose-message").workers.add(
- new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,origin) => {
const {user,ticket} = params
const hours: number = ticket.get("opendiscord:autoclose-hours").value
- const description = (source == "leave") ? lang.getTranslation("actions.descriptions.autocloseLeave") : lang.getTranslationWithParams("actions.descriptions.autocloseTimeout",[hours.toString()])
+ const description = (origin == "leave") ? lang.getTranslation("actions.descriptions.autocloseLeave") : lang.getTranslationWithParams("actions.descriptions.autocloseTimeout",[hours.toString()])
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
@@ -1242,10 +1266,10 @@ const autoEmbeds = () => {
//AUTODELETE MESSAGE
embeds.add(new api.ODEmbed("opendiscord:autodelete-message"))
embeds.get("opendiscord:autodelete-message").workers.add(
- new api.ODWorker("opendiscord:autodelete-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autodelete-message",0,async (instance,params,origin) => {
const {user,ticket} = params
const days: number = ticket.get("opendiscord:autodelete-days").value
- const description = (source == "leave") ? lang.getTranslation("actions.descriptions.autodeleteLeave") : lang.getTranslationWithParams("actions.descriptions.autodeleteTimeout",[days.toString()])
+ const description = (origin == "leave") ? lang.getTranslation("actions.descriptions.autodeleteLeave") : lang.getTranslationWithParams("actions.descriptions.autodeleteTimeout",[days.toString()])
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
@@ -1258,56 +1282,56 @@ const autoEmbeds = () => {
//AUTOCLOSE ENABLE
embeds.add(new api.ODEmbed("opendiscord:autoclose-enable"))
embeds.get("opendiscord:autoclose-enable").workers.add(
- new api.ODWorker("opendiscord:autoclose-enable",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autoclose-enable",0,async (instance,params,origin) => {
const {user,ticket,reason,time} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("โฑ๏ธ",lang.getTranslation("actions.titles.autocloseEnabled")))
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 ?? "/")+"```"})
})
)
//AUTODELETE ENABLE
embeds.add(new api.ODEmbed("opendiscord:autodelete-enable"))
embeds.get("opendiscord:autodelete-enable").workers.add(
- new api.ODWorker("opendiscord:autodelete-enable",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autodelete-enable",0,async (instance,params,origin) => {
const {user,ticket,reason,time} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("โฑ๏ธ",lang.getTranslation("actions.titles.autodeleteEnabled")))
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 ?? "/")+"```"})
})
)
//AUTOCLOSE DISABLE
embeds.add(new api.ODEmbed("opendiscord:autoclose-disable"))
embeds.get("opendiscord:autoclose-disable").workers.add(
- new api.ODWorker("opendiscord:autoclose-disable",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autoclose-disable",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("โฑ๏ธ",lang.getTranslation("actions.titles.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 ?? "/")+"```"})
})
)
//AUTODELETE DISABLE
embeds.add(new api.ODEmbed("opendiscord:autodelete-disable"))
embeds.get("opendiscord:autodelete-disable").workers.add(
- new api.ODWorker("opendiscord:autodelete-disable",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autodelete-disable",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("โฑ๏ธ",lang.getTranslation("actions.titles.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 ?? "/")+"```"})
})
)
}
@@ -1316,7 +1340,7 @@ const extraEmbeds = () => {
//TOPIC SET
embeds.add(new api.ODEmbed("opendiscord:topic-set"))
embeds.get("opendiscord:topic-set").workers.add(
- new api.ODWorker("opendiscord:topic-set",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:topic-set",0,async (instance,params,origin) => {
const {user,topic} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
@@ -1330,21 +1354,21 @@ const extraEmbeds = () => {
//PRIORITY SET
embeds.add(new api.ODEmbed("opendiscord:priority-set"))
embeds.get("opendiscord:priority-set").workers.add(
- new api.ODWorker("opendiscord:priority-set",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:priority-set",0,async (instance,params,origin) => {
const {user,priority,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("๐จ",lang.getTranslation("actions.titles.prioritySet")))
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 ?? "/")+"```"})
})
)
//PRIORITY GET
embeds.add(new api.ODEmbed("opendiscord:priority-get"))
embeds.get("opendiscord:priority-get").workers.add(
- new api.ODWorker("opendiscord:priority-get",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:priority-get",0,async (instance,params,origin) => {
const {user,priority} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
@@ -1357,14 +1381,14 @@ const extraEmbeds = () => {
//TRANSFER MESSAGE
embeds.add(new api.ODEmbed("opendiscord:transfer-message"))
embeds.get("opendiscord:transfer-message").workers.add(
- new api.ODWorker("opendiscord:transfer-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transfer-message",0,async (instance,params,origin) => {
const {user,oldCreator,newCreator,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
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)]))
- 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 ?? "/")+"```"})
})
)
}
\ No newline at end of file
diff --git a/src/builders/files.ts b/src/builders/files.ts
index 9a30548..252a719 100644
--- a/src/builders/files.ts
+++ b/src/builders/files.ts
@@ -1,14 +1,14 @@
///////////////////////////////////////
//FILE BUILDERS
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const files = opendiscord.builders.files
const lang = opendiscord.languages
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
-export const registerAllFiles = async () => {
+export async function registerAllFiles(){
transcriptFiles()
}
@@ -17,7 +17,7 @@ const transcriptFiles = () => {
//TEXT TRANSCRIPT
files.add(new api.ODFile("opendiscord:text-transcript"))
files.get("opendiscord:text-transcript").workers.add(
- new api.ODWorker("opendiscord:text-transcript",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:text-transcript",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,result} = params
const fileMode = transcriptConfig.data.textTranscriptStyle.fileMode
diff --git a/src/builders/messages.ts b/src/builders/messages.ts
index 0b89c1b..7b49b23 100644
--- a/src/builders/messages.ts
+++ b/src/builders/messages.ts
@@ -1,7 +1,7 @@
///////////////////////////////////////
//MESSAGE BUILDERS
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const messages = opendiscord.builders.messages
@@ -12,8 +12,7 @@ const embeds = opendiscord.builders.embeds
const lang = opendiscord.languages
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerAllMessages = async () => {
- verifyBarMessages()
+export async function registerAllMessages(){
errorMessages()
helpMenuMessages()
statsMessages()
@@ -27,314 +26,13 @@ export const registerAllMessages = async () => {
extraMessages()
}
-const verifyBarMessages = () => {
- //VERIFYBAR TICKET MESSAGE
- messages.add(new api.ODMessage("opendiscord:verifybar-ticket-message"))
- messages.get("opendiscord:verifybar-ticket-message").workers.add(
- new api.ODWorker("opendiscord:verifybar-ticket-message",0,async (instance,params,source) => {
- const {guild,channel,user,verifybar} = params
- if (!guild){
- instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-ticket-message`")
- return
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket){
- instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-ticket-message`")
- return
- }
- const option = ticket.option
-
- //add pings
- const pingOptions = option.get("opendiscord:ticket-message-ping").value
- const pings: string[] = []
- const creator = ticket.get("opendiscord:opened-by").value
- if (creator) pings.push(discord.userMention(creator))
- if (pingOptions["@everyone"]) pings.push("@everyone")
- if (pingOptions["@here"]) pings.push("@here")
- pingOptions.custom.forEach((ping) => pings.push(discord.roleMention(ping)))
- const pingText = (pings.length > 0) ? pings.join(" ")+"\n" : ""
-
- //add text
- const text = option.get("opendiscord:ticket-message-text").value
- if (text !== "") instance.setContent(pingText+text)
- else instance.setContent(pingText)
-
- //add embed
- if (option.get("opendiscord:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
-
- //add verifybar components
- if (verifybar.id.value == "opendiscord:claim-ticket-ticket-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:unclaim-ticket-ticket-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:pin-ticket-ticket-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:unpin-ticket-ticket-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:close-ticket-ticket-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:reopen-ticket-ticket-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:delete-ticket-ticket-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
- if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"๐",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"}))
- }
- })
- )
-
- //TICKET CLOSED
- messages.add(new api.ODMessage("opendiscord:verifybar-close-message"))
- messages.get("opendiscord:verifybar-close-message").workers.add(
- new api.ODWorker("opendiscord:verifybar-close-message",0,async (instance,params,source) => {
- const {guild,channel,user,verifybar,originalMessage} = params
- if (!guild){
- instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-close-message`")
- return
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket){
- instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-close-message`")
- return
- }
-
- const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- //add embed
- instance.addEmbed(await embeds.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason}))
-
- //add verifybar components
- if (verifybar.id.value == "opendiscord:reopen-ticket-close-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:delete-ticket-close-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
- if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"๐",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"}))
- }
- })
- )
-
- //TICKET REOPENED
- messages.add(new api.ODMessage("opendiscord:verifybar-reopen-message"))
- messages.get("opendiscord:verifybar-reopen-message").workers.add(
- new api.ODWorker("opendiscord:verifybar-reopen-message",0,async (instance,params,source) => {
- const {guild,channel,user,verifybar,originalMessage} = params
- if (!guild){
- instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-reopen-message`")
- return
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket){
- instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-reopen-message`")
- return
- }
-
- const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- //add embed
- instance.addEmbed(await embeds.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
-
- //add verifybar components
- if (verifybar.id.value == "opendiscord:close-ticket-reopen-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:delete-ticket-reopen-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
- if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"๐",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"}))
- }
- })
- )
-
- //TICKET CLAIM
- messages.add(new api.ODMessage("opendiscord:verifybar-claim-message"))
- messages.get("opendiscord:verifybar-claim-message").workers.add(
- new api.ODWorker("opendiscord:verifybar-claim-message",0,async (instance,params,source) => {
- const {guild,channel,user,verifybar,originalMessage} = params
- if (!guild){
- instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-claim-message`")
- return
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket){
- instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-claim-message`")
- return
- }
-
- const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- //add embed
- instance.addEmbed(await embeds.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason}))
-
- //add verifybar components
- if (verifybar.id.value == "opendiscord:unclaim-ticket-claim-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
- }
- })
- )
-
- //TICKET UNCLAIM
- messages.add(new api.ODMessage("opendiscord:verifybar-unclaim-message"))
- messages.get("opendiscord:verifybar-unclaim-message").workers.add(
- new api.ODWorker("opendiscord:verifybar-unclaim-message",0,async (instance,params,source) => {
- const {guild,channel,user,verifybar,originalMessage} = params
- if (!guild){
- instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-unclaim-message`")
- return
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket){
- instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-unclaim-message`")
- return
- }
-
- const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- //add embed
- instance.addEmbed(await embeds.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason}))
-
- //add verifybar components
- if (verifybar.id.value == "opendiscord:claim-ticket-unclaim-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
- }
- })
- )
-
- //TICKET PIN
- messages.add(new api.ODMessage("opendiscord:verifybar-pin-message"))
- messages.get("opendiscord:verifybar-pin-message").workers.add(
- new api.ODWorker("opendiscord:verifybar-pin-message",0,async (instance,params,source) => {
- const {guild,channel,user,verifybar,originalMessage} = params
- if (!guild){
- instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-pin-message`")
- return
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket){
- instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-pin-message`")
- return
- }
-
- const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- //add embed
- instance.addEmbed(await embeds.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason}))
-
- //add verifybar components
- if (verifybar.id.value == "opendiscord:unpin-ticket-pin-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
- }
- })
- )
-
- //TICKET UNPIN
- messages.add(new api.ODMessage("opendiscord:verifybar-unpin-message"))
- messages.get("opendiscord:verifybar-unpin-message").workers.add(
- new api.ODWorker("opendiscord:verifybar-unpin-message",0,async (instance,params,source) => {
- const {guild,channel,user,verifybar,originalMessage} = params
- if (!guild){
- instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-unpin-message`")
- return
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket){
- instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-unpin-message`")
- return
- }
-
- const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null
- const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
-
- //add embed
- instance.addEmbed(await embeds.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason}))
-
- //add verifybar components
- if (verifybar.id.value == "opendiscord:pin-ticket-unpin-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
- }
- })
- )
-
- //TICKET AUTOCLOSED
- messages.add(new api.ODMessage("opendiscord:verifybar-autoclose-message"))
- messages.get("opendiscord:verifybar-autoclose-message").workers.add(
- new api.ODWorker("opendiscord:verifybar-autoclose-message",0,async (instance,params,source) => {
- const {guild,channel,user,verifybar,originalMessage} = params
- if (!guild || channel.isDMBased()){
- instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-autoclose-message`")
- return
- }
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket){
- instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-autoclose-message`")
- return
- }
-
- //add embed
- instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-message").build("other",{guild,channel,user,ticket}))
-
- //add verifybar components
- if (verifybar.id.value == "opendiscord:reopen-ticket-autoclose-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
-
- }else if (verifybar.id.value == "opendiscord:delete-ticket-autoclose-message"){
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar}))
- instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar}))
- if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"โ๏ธ",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"}))
- if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"๐",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"}))
- }
- })
- )
-}
-
const errorMessages = () => {
//ERROR
messages.add(new api.ODMessage("opendiscord:error"))
messages.get("opendiscord:error").workers.add(
- new api.ODWorker("opendiscord:error",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error",0,async (instance,params,origin) => {
const {guild,channel,user,error,layout,customTitle} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error").build(source,{guild,channel,user,error,layout,customTitle}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error").build(origin,{guild,channel,user,error,layout,customTitle}))
instance.setEphemeral(true)
})
)
@@ -342,9 +40,9 @@ const errorMessages = () => {
//ERROR OPTION MISSING
messages.add(new api.ODMessage("opendiscord:error-option-missing"))
messages.get("opendiscord:error-option-missing").workers.add(
- new api.ODWorker("opendiscord:error-option-missing",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-option-missing",0,async (instance,params,origin) => {
const {guild,channel,user,error} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-option-missing").build(source,{guild,channel,user,error}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-option-missing").build(origin,{guild,channel,user,error}))
instance.setEphemeral(true)
})
)
@@ -352,9 +50,9 @@ const errorMessages = () => {
//ERROR OPTION INVALID
messages.add(new api.ODMessage("opendiscord:error-option-invalid"))
messages.get("opendiscord:error-option-invalid").workers.add(
- new api.ODWorker("opendiscord:error-option-invalid",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-option-invalid",0,async (instance,params,origin) => {
const {guild,channel,user,error} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-option-invalid").build(source,{guild,channel,user,error}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-option-invalid").build(origin,{guild,channel,user,error}))
instance.setEphemeral(true)
})
)
@@ -362,9 +60,9 @@ const errorMessages = () => {
//ERROR UNKNOWN COMMAND
messages.add(new api.ODMessage("opendiscord:error-unknown-command"))
messages.get("opendiscord:error-unknown-command").workers.add(
- new api.ODWorker("opendiscord:error-unknown-command",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-unknown-command",0,async (instance,params,origin) => {
const {guild,channel,user,error} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-unknown-command").build(source,{guild,channel,user,error}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-unknown-command").build(origin,{guild,channel,user,error}))
instance.setEphemeral(true)
})
)
@@ -372,9 +70,9 @@ const errorMessages = () => {
//ERROR NO PERMISSIONS
messages.add(new api.ODMessage("opendiscord:error-no-permissions"))
messages.get("opendiscord:error-no-permissions").workers.add(
- new api.ODWorker("opendiscord:error-no-permissions",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-no-permissions",0,async (instance,params,origin) => {
const {guild,channel,user,permissions} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions").build(origin,{guild,channel,user,permissions}))
instance.setEphemeral(true)
})
)
@@ -382,9 +80,9 @@ const errorMessages = () => {
//ERROR NO PERMISSIONS COOLDOWN
messages.add(new api.ODMessage("opendiscord:error-no-permissions-cooldown"))
messages.get("opendiscord:error-no-permissions-cooldown").workers.add(
- new api.ODWorker("opendiscord:error-no-permissions-cooldown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-no-permissions-cooldown",0,async (instance,params,origin) => {
const {guild,channel,user,until} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-cooldown").build(source,{guild,channel,user,until}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-cooldown").build(origin,{guild,channel,user,until}))
instance.setEphemeral(true)
})
)
@@ -392,9 +90,9 @@ const errorMessages = () => {
//ERROR NO PERMISSIONS BLACKLISTED
messages.add(new api.ODMessage("opendiscord:error-no-permissions-blacklisted"))
messages.get("opendiscord:error-no-permissions-blacklisted").workers.add(
- new api.ODWorker("opendiscord:error-no-permissions-blacklisted",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-no-permissions-blacklisted",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-blacklisted").build(source,{guild,channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-blacklisted").build(origin,{guild,channel,user}))
instance.setEphemeral(true)
})
)
@@ -402,9 +100,9 @@ const errorMessages = () => {
//ERROR NO PERMISSIONS LIMITS
messages.add(new api.ODMessage("opendiscord:error-no-permissions-limits"))
messages.get("opendiscord:error-no-permissions-limits").workers.add(
- new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,origin) => {
const {guild,channel,user,limit} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild,channel,user,limit}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-limits").build(origin,{guild,channel,user,limit}))
instance.setEphemeral(true)
})
)
@@ -412,9 +110,9 @@ const errorMessages = () => {
//ERROR RESPONDER TIMEOUT
messages.add(new api.ODMessage("opendiscord:error-responder-timeout"))
messages.get("opendiscord:error-responder-timeout").workers.add(
- new api.ODWorker("opendiscord:error-responder-timeout",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-responder-timeout",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-responder-timeout").build(source,{guild,channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-responder-timeout").build(origin,{guild,channel,user}))
instance.setEphemeral(true)
})
)
@@ -422,9 +120,9 @@ const errorMessages = () => {
//ERROR TICKET UNKNOWN
messages.add(new api.ODMessage("opendiscord:error-ticket-unknown"))
messages.get("opendiscord:error-ticket-unknown").workers.add(
- new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-unknown").build(source,{guild,channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-unknown").build(origin,{guild,channel,user}))
instance.setEphemeral(true)
})
)
@@ -432,10 +130,10 @@ const errorMessages = () => {
//ERROR TICKET DEPRECATED
messages.add(new api.ODMessage("opendiscord:error-ticket-deprecated"))
messages.get("opendiscord:error-ticket-deprecated").workers.add(
- new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-deprecated").build(source,{guild,channel,user}))
- instance.addComponent(await buttons.getSafe("opendiscord:error-ticket-deprecated-transcript").build(source,{}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-deprecated").build(origin,{guild,channel,user}))
+ instance.addComponent(await buttons.getSafe("opendiscord:error-ticket-deprecated-transcript").build(origin,{}))
instance.setEphemeral(true)
})
)
@@ -443,9 +141,9 @@ const errorMessages = () => {
//ERROR OPTION UNKNOWN
messages.add(new api.ODMessage("opendiscord:error-option-unknown"))
messages.get("opendiscord:error-option-unknown").workers.add(
- new api.ODWorker("opendiscord:error-option-unknown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-option-unknown",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-option-unknown").build(source,{guild,channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-option-unknown").build(origin,{guild,channel,user}))
instance.setEphemeral(true)
})
)
@@ -453,9 +151,9 @@ const errorMessages = () => {
//ERROR PANEL UNKNOWN
messages.add(new api.ODMessage("opendiscord:error-panel-unknown"))
messages.get("opendiscord:error-panel-unknown").workers.add(
- new api.ODWorker("opendiscord:error-panel-unknown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-panel-unknown",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-panel-unknown").build(source,{guild,channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-panel-unknown").build(origin,{guild,channel,user}))
instance.setEphemeral(true)
})
)
@@ -463,9 +161,9 @@ const errorMessages = () => {
//ERROR NOT IN GUILD
messages.add(new api.ODMessage("opendiscord:error-not-in-guild"))
messages.get("opendiscord:error-not-in-guild").workers.add(
- new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,origin) => {
const {channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-not-in-guild").build(origin,{channel,user}))
instance.setEphemeral(true)
})
)
@@ -473,9 +171,19 @@ const errorMessages = () => {
//ERROR CHANNEL RENAME
messages.add(new api.ODMessage("opendiscord:error-channel-rename"))
messages.get("opendiscord:error-channel-rename").workers.add(
- new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,origin) => {
const {guild,channel,user,originalName,newName} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-channel-rename").build(source,{guild,channel,user,originalName,newName}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-channel-rename").build(origin,{guild,channel,user,originalName,newName}))
+ instance.setEphemeral(true)
+ })
+ )
+
+ //ERROR CHANNEL CATEGORY
+ messages.add(new api.ODMessage("opendiscord:error-channel-category"))
+ messages.get("opendiscord:error-channel-category").workers.add(
+ new api.ODWorker("opendiscord:error-channel-category",0,async (instance,params,origin) => {
+ const {guild,channel,user,originalCategory,newCategory} = params
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-channel-category").build(origin,{guild,channel,user,originalCategory,newCategory}))
instance.setEphemeral(true)
})
)
@@ -483,9 +191,9 @@ const errorMessages = () => {
//ERROR TICKET BUSY
messages.add(new api.ODMessage("opendiscord:error-ticket-busy"))
messages.get("opendiscord:error-ticket-busy").workers.add(
- new api.ODWorker("opendiscord:error-ticket-busy",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:error-ticket-busy",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-busy").build(source,{guild,channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-busy").build(origin,{guild,channel,user}))
instance.setEphemeral(true)
})
)
@@ -495,20 +203,20 @@ const helpMenuMessages = () => {
//HELP MENU
messages.add(new api.ODMessage("opendiscord:help-menu"))
messages.get("opendiscord:help-menu").workers.add(
- new api.ODWorker("opendiscord:help-menu",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:help-menu",0,async (instance,params,origin) => {
const {mode,page} = params
const totalPages = (await opendiscord.helpmenu.render(mode)).length
- const embed = await embeds.getSafe("opendiscord:help-menu").build(source,{mode,page})
+ const embed = await embeds.getSafe("opendiscord:help-menu").build(origin,{mode,page})
instance.addEmbed(embed)
if (totalPages > 1){
//when more than 1 page
- instance.addComponent(await buttons.getSafe("opendiscord:help-menu-previous").build(source,{mode,page}))
- instance.addComponent(await buttons.getSafe("opendiscord:help-menu-page").build(source,{mode,page}))
- instance.addComponent(await buttons.getSafe("opendiscord:help-menu-next").build(source,{mode,page}))
+ instance.addComponent(await buttons.getSafe("opendiscord:help-menu-previous").build(origin,{mode,page}))
+ instance.addComponent(await buttons.getSafe("opendiscord:help-menu-page").build(origin,{mode,page}))
+ instance.addComponent(await buttons.getSafe("opendiscord:help-menu-next").build(origin,{mode,page}))
instance.addComponent(buttons.getNewLine("opendiscord:help-menu-divider"))
}
- if (generalConfig.data.textCommands && generalConfig.data.slashCommands) instance.addComponent(await buttons.get("opendiscord:help-menu-switch").build(source,{mode,page}))
+ if (generalConfig.data.textCommands && generalConfig.data.slashCommands) instance.addComponent(await buttons.get("opendiscord:help-menu-switch").build(origin,{mode,page}))
})
)
}
@@ -517,45 +225,45 @@ const statsMessages = () => {
//STATS GLOBAL
messages.add(new api.ODMessage("opendiscord:stats-global"))
messages.get("opendiscord:stats-global").workers.add(
- new api.ODWorker("opendiscord:stats-global",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:stats-global",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:stats-global").build(source,{guild,channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:stats-global").build(origin,{guild,channel,user}))
})
)
//STATS TICKET
messages.add(new api.ODMessage("opendiscord:stats-ticket"))
messages.get("opendiscord:stats-ticket").workers.add(
- new api.ODWorker("opendiscord:stats-ticket",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:stats-ticket",0,async (instance,params,origin) => {
const {guild,channel,user,scopeData} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:stats-ticket").build(source,{guild,channel,user,scopeData}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:stats-ticket").build(origin,{guild,channel,user,scopeData}))
})
)
//STATS USER
messages.add(new api.ODMessage("opendiscord:stats-user"))
messages.get("opendiscord:stats-user").workers.add(
- new api.ODWorker("opendiscord:stats-user",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:stats-user",0,async (instance,params,origin) => {
const {guild,channel,user,scopeData} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:stats-user").build(source,{guild,channel,user,scopeData}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:stats-user").build(origin,{guild,channel,user,scopeData}))
})
)
//STATS RESET
messages.add(new api.ODMessage("opendiscord:stats-reset"))
messages.get("opendiscord:stats-reset").workers.add(
- new api.ODWorker("opendiscord:stats-reset",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:stats-reset",0,async (instance,params,origin) => {
const {guild,channel,user,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:stats-reset").build(source,{guild,channel,user,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:stats-reset").build(origin,{guild,channel,user,reason}))
})
)
//STATS TICKET UNKNOWN
messages.add(new api.ODMessage("opendiscord:stats-ticket-unknown"))
messages.get("opendiscord:stats-ticket-unknown").workers.add(
- new api.ODWorker("opendiscord:stats-ticket-unknown",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:stats-ticket-unknown",0,async (instance,params,origin) => {
const {guild,channel,user,id} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:stats-ticket-unknown").build(source,{guild,channel,user,id}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:stats-ticket-unknown").build(origin,{guild,channel,user,id}))
instance.setEphemeral(true)
})
)
@@ -565,7 +273,7 @@ const panelMessages = () => {
//PANEL
messages.add(new api.ODMessage("opendiscord:panel"))
messages.get("opendiscord:panel").workers.add([
- new api.ODWorker("opendiscord:panel-layout",1,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:panel-layout",1,async (instance,params,origin) => {
const {guild,channel,user,panel} = params
//add text
@@ -578,15 +286,15 @@ const panelMessages = () => {
instance.setContent(text)
}
- if (panel.get("opendiscord:enable-max-tickets-warning-text").value && generalConfig.data.system.limits.enabled){
- instance.setContent(instance.data.content+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*")
+ 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.ticketSystem.limits.userMaximum.toString()])+"*")
}
//add embed
const embedOptions = panel.get("opendiscord:embed").value
- if (embedOptions.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:panel").build(source,{guild,channel,user,panel}))
+ if (embedOptions.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:panel").build(origin,{guild,channel,user,panel}))
}),
- new api.ODWorker("opendiscord:panel-components",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:panel-components",0,async (instance,params,origin) => {
const {guild,channel,user,panel} = params
const options: api.ODOption[] = []
panel.get("opendiscord:options").value.forEach((id) => {
@@ -600,13 +308,13 @@ const panelMessages = () => {
options.forEach((option) => {
if (option instanceof api.ODTicketOption) ticketOptions.push(option)
})
- instance.addComponent(await dropdowns.getSafe("opendiscord:panel-dropdown-tickets").build(source,{guild,channel,user,panel,options:ticketOptions}))
+ instance.addComponent(await dropdowns.getSafe("opendiscord:panel-dropdown-tickets").build(origin,{guild,channel,user,panel,options:ticketOptions}))
}else{
//buttons
for (const option of options){
- if (option instanceof api.ODTicketOption) instance.addComponent(await buttons.getSafe("opendiscord:ticket-option").build(source,{guild,channel,user,panel,option}))
- else if (option instanceof api.ODWebsiteOption) instance.addComponent(await buttons.getSafe("opendiscord:website-option").build(source,{guild,channel,user,panel,option}))
- else if (option instanceof api.ODRoleOption) instance.addComponent(await buttons.getSafe("opendiscord:role-option").build(source,{guild,channel,user,panel,option}))
+ if (option instanceof api.ODTicketOption) instance.addComponent(await buttons.getSafe("opendiscord:ticket-option").build(origin,{guild,channel,user,panel,option}))
+ else if (option instanceof api.ODWebsiteOption) instance.addComponent(await buttons.getSafe("opendiscord:website-option").build(origin,{guild,channel,user,panel,option}))
+ else if (option instanceof api.ODRoleOption) instance.addComponent(await buttons.getSafe("opendiscord:role-option").build(origin,{guild,channel,user,panel,option}))
}
}
})
@@ -615,7 +323,7 @@ const panelMessages = () => {
//PANEL READY
messages.add(new api.ODMessage("opendiscord:panel-ready"))
messages.get("opendiscord:panel-ready").workers.add(
- new api.ODWorker("opendiscord:panel-ready",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:panel-ready",0,async (instance,params,origin) => {
instance.setContent("## "+lang.getTranslation("actions.descriptions.panelReady"))
instance.setEphemeral(true)
})
@@ -626,10 +334,10 @@ const ticketMessages = () => {
//TICKET CREATED
messages.add(new api.ODMessage("opendiscord:ticket-created"))
messages.get("opendiscord:ticket-created").workers.add(
- new api.ODWorker("opendiscord:ticket-created",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-created",0,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created").build(source,{guild,channel,user,ticket}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created").build(origin,{guild,channel,user,ticket}))
instance.addComponent(await buttons.getSafe("opendiscord:visit-ticket").build("ticket-created",{guild,channel,user,ticket}))
instance.setEphemeral(true)
})
@@ -638,7 +346,7 @@ const ticketMessages = () => {
//TICKET CREATED DM
messages.add(new api.ODMessage("opendiscord:ticket-created-dm"))
messages.get("opendiscord:ticket-created-dm").workers.add(
- new api.ODWorker("opendiscord:ticket-created-dm",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-created-dm",0,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
//add text
@@ -646,7 +354,7 @@ const ticketMessages = () => {
if (text !== "") instance.setContent(text)
//add embed
- if (ticket.option.get("opendiscord:dm-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created-dm").build(source,{guild,channel,user,ticket}))
+ if (ticket.option.get("opendiscord:dm-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created-dm").build(origin,{guild,channel,user,ticket}))
//add components
instance.addComponent(await buttons.getSafe("opendiscord:visit-ticket").build("ticket-created",{guild,channel,user,ticket}))
@@ -656,10 +364,10 @@ const ticketMessages = () => {
//TICKET CREATED LOGS
messages.add(new api.ODMessage("opendiscord:ticket-created-logs"))
messages.get("opendiscord:ticket-created-logs").workers.add(
- new api.ODWorker("opendiscord:ticket-created-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-created-logs",0,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created-logs").build(source,{guild,channel,user,ticket}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created-logs").build(origin,{guild,channel,user,ticket}))
instance.addComponent(await buttons.getSafe("opendiscord:visit-ticket").build("ticket-created",{guild,channel,user,ticket}))
})
)
@@ -667,7 +375,7 @@ const ticketMessages = () => {
//TICKET MESSAGE
messages.add(new api.ODMessage("opendiscord:ticket-message"))
messages.get("opendiscord:ticket-message").workers.add([
- new api.ODWorker("opendiscord:ticket-message-layout",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-message-layout",0,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
//add pings
@@ -686,12 +394,12 @@ const ticketMessages = () => {
else instance.setContent(pingText)
//add embed
- if (ticket.option.get("opendiscord:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:ticket-message").build(source,{guild,channel,user,ticket}))
+ if (ticket.option.get("opendiscord:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:ticket-message").build(origin,{guild,channel,user,ticket}))
}),
- new api.ODWorker("opendiscord:ticket-message-components",1,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-message-components",1,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
//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
if (ticket.get("opendiscord:claimed").value){
instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -699,7 +407,7 @@ const ticketMessages = () => {
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
if (ticket.get("opendiscord:pinned").value){
instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -707,7 +415,7 @@ const ticketMessages = () => {
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
if (ticket.get("opendiscord:closed").value){
instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -716,9 +424,9 @@ const ticketMessages = () => {
}
}
//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,source) => {
+ new api.ODWorker("opendiscord:ticket-message-disable-components",2,async (instance,params,origin) => {
const {ticket} = params
if (ticket.get("opendiscord:for-deletion").value){
//disable all buttons when ticket is being prepared for deletion
@@ -734,125 +442,125 @@ const ticketMessages = () => {
//TICKET CLOSED
messages.add(new api.ODMessage("opendiscord:close-message"))
messages.get("opendiscord:close-message").workers.add(
- new api.ODWorker("opendiscord:close-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:close-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:close-message").build(source,{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.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("close-message",{guild,channel,user,ticket}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:close-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (generalConfig.data.ticketSystem.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-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}))
})
)
//TICKET REOPENED
messages.add(new api.ODMessage("opendiscord:reopen-message"))
messages.get("opendiscord:reopen-message").workers.add(
- new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:reopen-message").build(source,{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.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("reopen-message",{guild,channel,user,ticket}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:reopen-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (generalConfig.data.ticketSystem.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:close-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}))
})
)
//TICKET DELETED
messages.add(new api.ODMessage("opendiscord:delete-message"))
messages.get("opendiscord:delete-message").workers.add(
- new api.ODWorker("opendiscord:delete-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:delete-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:delete-message").build(source,{guild,channel,user,ticket,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:delete-message").build(origin,{guild,channel,user,ticket,reason}))
})
)
//TICKET CLAIMED
messages.add(new api.ODMessage("opendiscord:claim-message"))
messages.get("opendiscord:claim-message").workers.add(
- new api.ODWorker("opendiscord:claim-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:claim-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:claim-message").build(source,{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}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:claim-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (generalConfig.data.ticketSystem.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("claim-message",{guild,channel,user,ticket}))
})
)
//TICKET UNCLAIMED
messages.add(new api.ODMessage("opendiscord:unclaim-message"))
messages.get("opendiscord:unclaim-message").workers.add(
- new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:unclaim-message").build(source,{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}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:unclaim-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (generalConfig.data.ticketSystem.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("unclaim-message",{guild,channel,user,ticket}))
})
)
//TICKET PINNED
messages.add(new api.ODMessage("opendiscord:pin-message"))
messages.get("opendiscord:pin-message").workers.add(
- new api.ODWorker("opendiscord:pin-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:pin-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:pin-message").build(source,{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}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:pin-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (generalConfig.data.ticketSystem.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("pin-message",{guild,channel,user,ticket}))
})
)
//TICKET UNPINNED
messages.add(new api.ODMessage("opendiscord:unpin-message"))
messages.get("opendiscord:unpin-message").workers.add(
- new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:unpin-message").build(source,{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}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:unpin-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (generalConfig.data.ticketSystem.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("unpin-message",{guild,channel,user,ticket}))
})
)
//TICKET RENAMED
messages.add(new api.ODMessage("opendiscord:rename-message"))
messages.get("opendiscord:rename-message").workers.add(
- new api.ODWorker("opendiscord:rename-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:rename-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason,data} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:rename-message").build(source,{guild,channel,user,ticket,reason,data}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:rename-message").build(origin,{guild,channel,user,ticket,reason,data}))
})
)
//TICKET MOVED
messages.add(new api.ODMessage("opendiscord:move-message"))
messages.get("opendiscord:move-message").workers.add(
- new api.ODWorker("opendiscord:move-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:move-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason,data} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:move-message").build(source,{guild,channel,user,ticket,reason,data}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:move-message").build(origin,{guild,channel,user,ticket,reason,data}))
})
)
//TICKET USER ADDED
messages.add(new api.ODMessage("opendiscord:add-message"))
messages.get("opendiscord:add-message").workers.add(
- new api.ODWorker("opendiscord:add-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:add-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason,data} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:add-message").build(source,{guild,channel,user,ticket,reason,data}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:add-message").build(origin,{guild,channel,user,ticket,reason,data}))
})
)
//TICKET USER REMOVED
messages.add(new api.ODMessage("opendiscord:remove-message"))
messages.get("opendiscord:remove-message").workers.add(
- new api.ODWorker("opendiscord:remove-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:remove-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason,data} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:remove-message").build(source,{guild,channel,user,ticket,reason,data}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:remove-message").build(origin,{guild,channel,user,ticket,reason,data}))
})
)
//TICKET ACTION DM
messages.add(new api.ODMessage("opendiscord:ticket-action-dm"))
messages.get("opendiscord:ticket-action-dm").workers.add(
- new api.ODWorker("opendiscord:ticket-action-dm",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-action-dm",0,async (instance,params,origin) => {
const {guild,channel,user,mode,ticket,reason,additionalData} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,mode,ticket,reason,additionalData}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,mode,ticket,reason,additionalData}))
})
)
//TICKET ACTION LOGS
messages.add(new api.ODMessage("opendiscord:ticket-action-logs"))
messages.get("opendiscord:ticket-action-logs").workers.add(
- new api.ODWorker("opendiscord:ticket-action-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-action-logs",0,async (instance,params,origin) => {
const {guild,channel,user,mode,ticket,reason,additionalData} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,mode,ticket,reason,additionalData}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,mode,ticket,reason,additionalData}))
})
)
}
@@ -861,54 +569,54 @@ const blacklistMessages = () => {
//BLACKLIST VIEW
messages.add(new api.ODMessage("opendiscord:blacklist-view"))
messages.get("opendiscord:blacklist-view").workers.add(
- new api.ODWorker("opendiscord:blacklist-view",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-view",0,async (instance,params,origin) => {
const {guild,channel,user} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-view").build(source,{guild,channel,user}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-view").build(origin,{guild,channel,user}))
})
)
//BLACKLIST GET
messages.add(new api.ODMessage("opendiscord:blacklist-get"))
messages.get("opendiscord:blacklist-get").workers.add(
- new api.ODWorker("opendiscord:blacklist-get",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-get",0,async (instance,params,origin) => {
const {guild,channel,user,data} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-get").build(source,{guild,channel,user,data}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-get").build(origin,{guild,channel,user,data}))
})
)
//BLACKLIST ADD
messages.add(new api.ODMessage("opendiscord:blacklist-add"))
messages.get("opendiscord:blacklist-add").workers.add(
- new api.ODWorker("opendiscord:blacklist-add",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-add",0,async (instance,params,origin) => {
const {guild,channel,user,data,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-add").build(source,{guild,channel,user,data,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-add").build(origin,{guild,channel,user,data,reason}))
})
)
//BLACKLIST REMOVE
messages.add(new api.ODMessage("opendiscord:blacklist-remove"))
messages.get("opendiscord:blacklist-remove").workers.add(
- new api.ODWorker("opendiscord:blacklist-remove",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-remove",0,async (instance,params,origin) => {
const {guild,channel,user,data,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-remove").build(source,{guild,channel,user,data,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-remove").build(origin,{guild,channel,user,data,reason}))
})
)
//BLACKLIST DM
messages.add(new api.ODMessage("opendiscord:blacklist-dm"))
messages.get("opendiscord:blacklist-dm").workers.add(
- new api.ODWorker("opendiscord:blacklist-dm",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-dm",0,async (instance,params,origin) => {
const {guild,channel,user,mode,data,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-dm").build(source,{guild,channel,user,mode,data,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-dm").build(origin,{guild,channel,user,mode,data,reason}))
})
)
//BLACKLIST LOGS
messages.add(new api.ODMessage("opendiscord:blacklist-logs"))
messages.get("opendiscord:blacklist-logs").workers.add(
- new api.ODWorker("opendiscord:blacklist-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:blacklist-logs",0,async (instance,params,origin) => {
const {guild,channel,user,mode,data,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-logs").build(source,{guild,channel,user,mode,data,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-logs").build(origin,{guild,channel,user,mode,data,reason}))
})
)
}
@@ -917,40 +625,40 @@ const transcriptMessages = () => {
//TRANSCRIPT TEXT READY
messages.add(new api.ODMessage("opendiscord:transcript-text-ready"))
messages.get("opendiscord:transcript-text-ready").workers.add(
- new api.ODWorker("opendiscord:transcript-text-ready",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-text-ready",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,result} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:transcript-text-ready").build(source,{guild,channel,user,ticket,compiler,result}))
- instance.addFile(await files.getSafe("opendiscord:text-transcript").build(source,{guild,channel,user,ticket,compiler,result}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:transcript-text-ready").build(origin,{guild,channel,user,ticket,compiler,result}))
+ instance.addFile(await files.getSafe("opendiscord:text-transcript").build(origin,{guild,channel,user,ticket,compiler,result}))
})
)
//TRANSCRIPT HTML READY
messages.add(new api.ODMessage("opendiscord:transcript-html-ready"))
messages.get("opendiscord:transcript-html-ready").workers.add(
- new api.ODWorker("opendiscord:transcript-html-ready",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-html-ready",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,result} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:transcript-html-ready").build(source,{guild,channel,user,ticket,compiler,result}))
- instance.addComponent(await buttons.getSafe("opendiscord:transcript-html-visit").build(source,{guild,channel,user,ticket,compiler,result}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:transcript-html-ready").build(origin,{guild,channel,user,ticket,compiler,result}))
+ instance.addComponent(await buttons.getSafe("opendiscord:transcript-html-visit").build(origin,{guild,channel,user,ticket,compiler,result}))
})
)
//TRANSCRIPT HTML PROGRESS
messages.add(new api.ODMessage("opendiscord:transcript-html-progress"))
messages.get("opendiscord:transcript-html-progress").workers.add(
- new api.ODWorker("opendiscord:transcript-html-progress",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-html-progress",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,remaining} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:transcript-html-progress").build(source,{guild,channel,user,ticket,compiler,remaining}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:transcript-html-progress").build(origin,{guild,channel,user,ticket,compiler,remaining}))
})
)
//TRANSCRIPT ERROR
messages.add(new api.ODMessage("opendiscord:transcript-error"))
messages.get("opendiscord:transcript-error").workers.add(
- new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason}))
- instance.addComponent(await buttons.getSafe("opendiscord:transcript-error-retry").build(source,{guild,channel,user,ticket,compiler,reason}))
- instance.addComponent(await buttons.getSafe("opendiscord:transcript-error-continue").build(source,{guild,channel,user,ticket,compiler,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:transcript-error").build(origin,{guild,channel,user,ticket,compiler,reason}))
+ instance.addComponent(await buttons.getSafe("opendiscord:transcript-error-retry").build(origin,{guild,channel,user,ticket,compiler,reason}))
+ instance.addComponent(await buttons.getSafe("opendiscord:transcript-error-continue").build(origin,{guild,channel,user,ticket,compiler,reason}))
})
)
}
@@ -959,9 +667,9 @@ const roleMessages = () => {
//REACTION ROLE
messages.add(new api.ODMessage("opendiscord:reaction-role"))
messages.get("opendiscord:reaction-role").workers.add(
- new api.ODWorker("opendiscord:reaction-role",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reaction-role",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:reaction-role").build(source,{guild,user,role,result}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:reaction-role").build(origin,{guild,user,role,result}))
instance.setEphemeral(true)
})
)
@@ -969,18 +677,18 @@ const roleMessages = () => {
//REACTION ROLE DM
messages.add(new api.ODMessage("opendiscord:reaction-role-dm"))
messages.get("opendiscord:reaction-role-dm").workers.add(
- new api.ODWorker("opendiscord:reaction-role-dm",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reaction-role-dm",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:reaction-role-dm").build(source,{guild,user,role,result}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:reaction-role-dm").build(origin,{guild,user,role,result}))
})
)
//REACTION ROLE LOGS
messages.add(new api.ODMessage("opendiscord:reaction-role-logs"))
messages.get("opendiscord:reaction-role-logs").workers.add(
- new api.ODWorker("opendiscord:reaction-role-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:reaction-role-logs",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:reaction-role-logs").build(source,{guild,user,role,result}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:reaction-role-logs").build(origin,{guild,user,role,result}))
})
)
}
@@ -989,10 +697,10 @@ const clearMessages = () => {
//CLEAR VERIFY MESSAGE
messages.add(new api.ODMessage("opendiscord:clear-verify-message"))
messages.get("opendiscord:clear-verify-message").workers.add(
- new api.ODWorker("opendiscord:clear-verify-message",0,async (instance,params,source) => {
- const {guild,channel,user,filter,list} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:clear-verify-message").build(source,{guild,channel,user,filter,list}))
- instance.addComponent(await buttons.getSafe("opendiscord:clear-continue").build(source,{guild,channel,user,filter,list}))
+ new api.ODWorker("opendiscord:clear-verify-message",0,async (instance,params,origin) => {
+ const {guild,channel,user,filter,list,inProgress} = params
+ instance.addEmbed(await embeds.getSafe("opendiscord:clear-verify-message").build(origin,{guild,channel,user,filter,list,inProgress}))
+ instance.addComponent(await buttons.getSafe("opendiscord:clear-continue").build(origin,{guild,channel,user,filter,list,inProgress}))
instance.setEphemeral(true)
})
)
@@ -1000,9 +708,9 @@ const clearMessages = () => {
//CLEAR MESSAGE
messages.add(new api.ODMessage("opendiscord:clear-message"))
messages.get("opendiscord:clear-message").workers.add(
- new api.ODWorker("opendiscord:clear-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:clear-message",0,async (instance,params,origin) => {
const {guild,channel,user,filter,list} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:clear-message").build(source,{guild,channel,user,filter,list}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:clear-message").build(origin,{guild,channel,user,filter,list}))
instance.setEphemeral(true)
})
)
@@ -1010,9 +718,9 @@ const clearMessages = () => {
//CLEAR LOGS
messages.add(new api.ODMessage("opendiscord:clear-logs"))
messages.get("opendiscord:clear-logs").workers.add(
- new api.ODWorker("opendiscord:clear-logs",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:clear-logs",0,async (instance,params,origin) => {
const {guild,channel,user,filter,list} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:clear-logs").build(source,{guild,channel,user,filter,list}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:clear-logs").build(origin,{guild,channel,user,filter,list}))
})
)
}
@@ -1021,56 +729,56 @@ const autoMessages = () => {
//AUTOCLOSE MESSAGE
messages.add(new api.ODMessage("opendiscord:autoclose-message"))
messages.get("opendiscord:autoclose-message").workers.add(
- new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-message").build(source,{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.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("autoclose-message",{guild,channel,user,ticket}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-message").build(origin,{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.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("autoclose-message",{guild,channel,user,ticket}))
})
)
//AUTODELETE MESSAGE
messages.add(new api.ODMessage("opendiscord:autodelete-message"))
messages.get("opendiscord:autodelete-message").workers.add(
- new api.ODWorker("opendiscord:autodelete-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autodelete-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-message").build(source,{guild,channel,user,ticket}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-message").build(origin,{guild,channel,user,ticket}))
})
)
//AUTOCLOSE ENABLE
messages.add(new api.ODMessage("opendiscord:autoclose-enable"))
messages.get("opendiscord:autoclose-enable").workers.add(
- new api.ODWorker("opendiscord:autoclose-enable",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autoclose-enable",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason,time} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-enable").build(origin,{guild,channel,user,ticket,reason,time}))
})
)
//AUTODELETE ENABLE
messages.add(new api.ODMessage("opendiscord:autodelete-enable"))
messages.get("opendiscord:autodelete-enable").workers.add(
- new api.ODWorker("opendiscord:autodelete-enable",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autodelete-enable",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason,time} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-enable").build(origin,{guild,channel,user,ticket,reason,time}))
})
)
//AUTOCLOSE DISABLE
messages.add(new api.ODMessage("opendiscord:autoclose-disable"))
messages.get("opendiscord:autoclose-disable").workers.add(
- new api.ODWorker("opendiscord:autoclose-disable",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autoclose-disable",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-disable").build(source,{guild,channel,user,ticket,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-disable").build(origin,{guild,channel,user,ticket,reason}))
})
)
//AUTODELETE DISABLE
messages.add(new api.ODMessage("opendiscord:autodelete-disable"))
messages.get("opendiscord:autodelete-disable").workers.add(
- new api.ODWorker("opendiscord:autodelete-disable",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:autodelete-disable",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-disable").build(source,{guild,channel,user,ticket,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-disable").build(origin,{guild,channel,user,ticket,reason}))
})
)
}
@@ -1079,36 +787,36 @@ const extraMessages = () => {
//TOPIC SET
messages.add(new api.ODMessage("opendiscord:topic-set"))
messages.get("opendiscord:topic-set").workers.add(
- new api.ODWorker("opendiscord:topic-set",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:topic-set",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,topic} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:topic-set").build(source,{guild,channel,user,ticket,topic}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:topic-set").build(origin,{guild,channel,user,ticket,topic}))
})
)
//PRIORITY SET
messages.add(new api.ODMessage("opendiscord:priority-set"))
messages.get("opendiscord:priority-set").workers.add(
- new api.ODWorker("opendiscord:priority-set",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:priority-set",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,priority,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:priority-set").build(source,{guild,channel,user,ticket,priority,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:priority-set").build(origin,{guild,channel,user,ticket,priority,reason}))
})
)
//PRIORITY GET
messages.add(new api.ODMessage("opendiscord:priority-get"))
messages.get("opendiscord:priority-get").workers.add(
- new api.ODWorker("opendiscord:priority-get",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:priority-get",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,priority} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:priority-get").build(source,{guild,channel,user,ticket,priority}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:priority-get").build(origin,{guild,channel,user,ticket,priority}))
})
)
//TRANSFER MESSAGE
messages.add(new api.ODMessage("opendiscord:transfer-message"))
messages.get("opendiscord:transfer-message").workers.add(
- new api.ODWorker("opendiscord:transfer-message",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:transfer-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,oldCreator,newCreator,reason} = params
- instance.addEmbed(await embeds.getSafe("opendiscord:transfer-message").build(source,{guild,channel,user,ticket,oldCreator,newCreator,reason}))
+ instance.addEmbed(await embeds.getSafe("opendiscord:transfer-message").build(origin,{guild,channel,user,ticket,oldCreator,newCreator,reason}))
})
)
}
\ No newline at end of file
diff --git a/src/builders/modals.ts b/src/builders/modals.ts
index df7d222..281e93f 100644
--- a/src/builders/modals.ts
+++ b/src/builders/modals.ts
@@ -1,23 +1,23 @@
///////////////////////////////////////
//MODAL BUILDERS
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const modals = opendiscord.builders.modals
const lang = opendiscord.languages
-export const registerAllModals = async () => {
+export async function registerAllModals(){
ticketModals()
}
const ticketModals = () => {
//TICKET QUESTIONS
modals.add(new api.ODModal("opendiscord:ticket-questions"))
modals.get("opendiscord:ticket-questions").workers.add(
- new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,source) => {
+ new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,origin) => {
const {option} = params
- instance.setCustomId("od:ticket-questions_"+option.id.value+"_"+source)
+ instance.setCustomId("od:ticket-questions_"+option.id.value+"_"+origin)
instance.setTitle(option.exists("opendiscord:name") ? option.get("opendiscord:name").value : option.id.value)
const questionIds = option.get("opendiscord:questions").value
questionIds.forEach((id) => {
@@ -30,7 +30,7 @@ const ticketModals = () => {
required:question.get("opendiscord:required").value,
placeholder:(question.get("opendiscord:placeholder").value) ? question.get("opendiscord:placeholder").value : undefined,
minLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-min").value : undefined,
- maxLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : undefined
+ maxLength:Math.min(1024-6,(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : (1024-6)) //embed field limit - 6x` characters
})
else if (question instanceof api.ODParagraphQuestion) instance.addQuestion({
customId:question.id.value,
@@ -39,7 +39,7 @@ const ticketModals = () => {
required:question.get("opendiscord:required").value,
placeholder:(question.get("opendiscord:placeholder").value) ? question.get("opendiscord:placeholder").value : undefined,
minLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-min").value : undefined,
- maxLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : undefined
+ maxLength:Math.min(1024-6,(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : (1024-6)) //embed field limit - 6x` characters
})
})
})
@@ -48,10 +48,10 @@ const ticketModals = () => {
//CLOSE TICKET REASON
modals.add(new api.ODModal("opendiscord:close-ticket-reason"))
modals.get("opendiscord:close-ticket-reason").workers.add(
- new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,source) => {
- const {ticket} = params
+ new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,origin) => {
+ const {channel,message} = params
- instance.setCustomId("od:close-ticket-reason_"+ticket.id.value+"_"+source)
+ instance.setCustomId("od:close-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.close"))
instance.addQuestion({
customId:"reason",
@@ -66,10 +66,10 @@ const ticketModals = () => {
//REOPEN TICKET REASON
modals.add(new api.ODModal("opendiscord:reopen-ticket-reason"))
modals.get("opendiscord:reopen-ticket-reason").workers.add(
- new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,source) => {
- const {ticket} = params
+ new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,origin) => {
+ const {channel,message} = params
- instance.setCustomId("od:reopen-ticket-reason_"+ticket.id.value+"_"+source)
+ instance.setCustomId("od:reopen-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.reopen"))
instance.addQuestion({
customId:"reason",
@@ -84,10 +84,10 @@ const ticketModals = () => {
//DELETE TICKET REASON
modals.add(new api.ODModal("opendiscord:delete-ticket-reason"))
modals.get("opendiscord:delete-ticket-reason").workers.add(
- new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,source) => {
- const {ticket} = params
+ new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,origin) => {
+ const {channel,message} = params
- instance.setCustomId("od:delete-ticket-reason_"+ticket.id.value+"_"+source)
+ instance.setCustomId("od:delete-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.delete"))
instance.addQuestion({
customId:"reason",
@@ -102,10 +102,10 @@ const ticketModals = () => {
//CLAIM TICKET REASON
modals.add(new api.ODModal("opendiscord:claim-ticket-reason"))
modals.get("opendiscord:claim-ticket-reason").workers.add(
- new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,source) => {
- const {ticket} = params
+ new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,origin) => {
+ const {channel,message} = params
- instance.setCustomId("od:claim-ticket-reason_"+ticket.id.value+"_"+source)
+ instance.setCustomId("od:claim-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.claim"))
instance.addQuestion({
customId:"reason",
@@ -120,10 +120,10 @@ const ticketModals = () => {
//UNCLAIM TICKET REASON
modals.add(new api.ODModal("opendiscord:unclaim-ticket-reason"))
modals.get("opendiscord:unclaim-ticket-reason").workers.add(
- new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,source) => {
- const {ticket} = params
+ new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,origin) => {
+ const {channel,message} = params
- instance.setCustomId("od:unclaim-ticket-reason_"+ticket.id.value+"_"+source)
+ instance.setCustomId("od:unclaim-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.unclaim"))
instance.addQuestion({
customId:"reason",
@@ -138,10 +138,10 @@ const ticketModals = () => {
//PIN TICKET REASON
modals.add(new api.ODModal("opendiscord:pin-ticket-reason"))
modals.get("opendiscord:pin-ticket-reason").workers.add(
- new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,source) => {
- const {ticket} = params
+ new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,origin) => {
+ const {channel,message} = params
- instance.setCustomId("od:pin-ticket-reason_"+ticket.id.value+"_"+source)
+ instance.setCustomId("od:pin-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.pin"))
instance.addQuestion({
customId:"reason",
@@ -156,10 +156,10 @@ const ticketModals = () => {
//UNPIN TICKET REASON
modals.add(new api.ODModal("opendiscord:unpin-ticket-reason"))
modals.get("opendiscord:unpin-ticket-reason").workers.add(
- new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,source) => {
- const {ticket} = params
+ new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,origin) => {
+ const {channel,message} = params
- instance.setCustomId("od:unpin-ticket-reason_"+ticket.id.value+"_"+source)
+ instance.setCustomId("od:unpin-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.unpin"))
instance.addQuestion({
customId:"reason",
diff --git a/src/commands/add.ts b/src/commands/add.ts
index 43d4b89..dd1dec6 100644
--- a/src/commands/add.ts
+++ b/src/commands/add.ts
@@ -1,45 +1,32 @@
///////////////////////////////////////
//ADD COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//ADD COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:add",generalConfig.data.prefix,"add"))
opendiscord.responders.commands.get("opendiscord:add").workers.add([
- new api.ODWorker("opendiscord:add",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:add",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.add,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check if in guild/Server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"add")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+ //fetch data
const data = instance.options.getUser("user",true)
const reason = instance.options.getString("reason",false)
@@ -52,15 +39,15 @@ export const registerCommandResponders = async () => {
//start adding user to ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:add-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(source,{guild,channel,user,ticket,reason,data}))
+ await opendiscord.actions.get("opendiscord:add-ticket-user").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,data})
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(origin,{guild,channel,user,ticket,reason,data}))
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'add' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/autoclose.ts b/src/commands/autoclose.ts
index bdf5a8b..ba66cf7 100644
--- a/src/commands/autoclose.ts
+++ b/src/commands/autoclose.ts
@@ -1,50 +1,33 @@
///////////////////////////////////////
//AUTOCLOSE COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//AUTOCLOSE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:autoclose",generalConfig.data.prefix,/^autoclose/))
opendiscord.responders.commands.get("opendiscord:autoclose").workers.add([
- new api.ODWorker("opendiscord:autoclose",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:autoclose",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.autoclose,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"autoclose")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
-
- //return when already closed
- if (ticket.get("opendiscord:closed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+ const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
+ if (!isTicketOpen) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
@@ -54,40 +37,27 @@ export const registerCommandResponders = async () => {
const reason = instance.options.getString("reason",false)
ticket.get("opendiscord:autoclose-enabled").value = false
ticket.get("opendiscord:autoclose-hours").value = 0
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-disable").build(source,{guild,channel,user,ticket,reason}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-disable").build(origin,{guild,channel,user,ticket,reason}))
}else if (scope == "enable"){
const time = instance.options.getNumber("time",true)
const reason = instance.options.getString("reason",false)
ticket.get("opendiscord:autoclose-enabled").value = true
ticket.get("opendiscord:autoclose-hours").value = time
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-enable").build(origin,{guild,channel,user,ticket,reason,time}))
}
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on autoclose "+scope+"!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
const reason = instance.options.getString("reason",false)
opendiscord.log(instance.user.displayName+" used the 'autoclose "+scope+"' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"reason",value:reason ?? "/"},
])
})
diff --git a/src/commands/autocomplete.ts b/src/commands/autocomplete.ts
index e7cac2a..2dbd7f2 100644
--- a/src/commands/autocomplete.ts
+++ b/src/commands/autocomplete.ts
@@ -1,13 +1,13 @@
///////////////////////////////////////
//AUTOCOMPLETE COMMAND UTILS
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
-export const registerAutocompleteResponders = async () => {
+export async function registerAutocompleteResponders(){
//PANEL ID AUTOCOMPLETE
opendiscord.responders.autocomplete.add(new api.ODAutocompleteResponder("opendiscord:panel-id","panel","id"))
- opendiscord.responders.autocomplete.get("opendiscord:panel-id").workers.add(new api.ODWorker("opendiscord:panel-id",0,async (instance,params,source,cancel) => {
+ opendiscord.responders.autocomplete.get("opendiscord:panel-id").workers.add(new api.ODWorker("opendiscord:panel-id",0,async (instance,params,origin,cancel) => {
//create panel choices
const panelChoices : {name:string, value:string}[] = []
opendiscord.configs.get("opendiscord:panels").data.forEach((panel) => {
@@ -19,7 +19,7 @@ export const registerAutocompleteResponders = async () => {
//OPTION ID AUTOCOMPLETE
opendiscord.responders.autocomplete.add(new api.ODAutocompleteResponder("opendiscord:option-id",/ticket|move/,"id"))
- opendiscord.responders.autocomplete.get("opendiscord:option-id").workers.add(new api.ODWorker("opendiscord:option-id",0,async (instance,params,source,cancel) => {
+ opendiscord.responders.autocomplete.get("opendiscord:option-id").workers.add(new api.ODWorker("opendiscord:option-id",0,async (instance,params,origin,cancel) => {
//create ticket choices
const ticketChoices : {name:string, value:string}[] = []
opendiscord.configs.get("opendiscord:options").data.forEach((option) => {
diff --git a/src/commands/autodelete.ts b/src/commands/autodelete.ts
index f912668..235c2cf 100644
--- a/src/commands/autodelete.ts
+++ b/src/commands/autodelete.ts
@@ -1,45 +1,30 @@
///////////////////////////////////////
//AUTODELETE COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//AUTODELETE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:autodelete",generalConfig.data.prefix,/^autodelete/))
opendiscord.responders.commands.get("opendiscord:autodelete").workers.add([
- new api.ODWorker("opendiscord:autodelete",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:autodelete",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.autodelete,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"autodelete")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
@@ -49,40 +34,27 @@ export const registerCommandResponders = async () => {
const reason = instance.options.getString("reason",false)
ticket.get("opendiscord:autodelete-enabled").value = false
ticket.get("opendiscord:autodelete-days").value = 0
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-disable").build(source,{guild,channel,user,ticket,reason}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-disable").build(origin,{guild,channel,user,ticket,reason}))
}else if (scope == "enable"){
const time = instance.options.getNumber("time",true)
const reason = instance.options.getString("reason",false)
ticket.get("opendiscord:autodelete-enabled").value = true
ticket.get("opendiscord:autodelete-days").value = time
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-enable").build(origin,{guild,channel,user,ticket,reason,time}))
}
- //update ticket message
- const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
- if (ticketMessage){
- try{
- ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
- }catch(e){
- opendiscord.log("Unable to edit ticket message on autodelete "+scope+"!","error",[
- {key:"channel",value:"#"+channel.name},
- {key:"channelid",value:channel.id,hidden:true},
- {key:"messageid",value:ticketMessage.id},
- {key:"option",value:ticket.option.id.value}
- ])
- opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
- }
- }
+ //update ticket message (no await)
+ openticketUtils.updateTicketMessage(guild,channel,user,ticket)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
const reason = instance.options.getString("reason",false)
opendiscord.log(instance.user.displayName+" used the 'autodelete "+scope+"' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"reason",value:reason ?? "/"},
])
})
diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts
index 16e8548..10d0d18 100644
--- a/src/commands/blacklist.ts
+++ b/src/commands/blacklist.ts
@@ -1,29 +1,29 @@
///////////////////////////////////////
//BLACKLIST COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//BLACKLIST COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:blacklist",generalConfig.data.prefix,/^blacklist/))
opendiscord.responders.commands.get("opendiscord:blacklist").workers.add([
- new api.ODWorker("opendiscord:blacklist",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:blacklist",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//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.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(source,{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"]}))
return cancel()
}
//check is in guild/server
if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
+ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(origin,{channel:instance.channel,user:instance.user}))
return cancel()
}
@@ -31,11 +31,11 @@ export const registerCommandResponders = async () => {
const scope = instance.options.getSubCommand()
if (!scope || (scope != "add" && scope != "get" && scope != "remove" && scope != "view")) return
if (scope == "view"){
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-view").build(source,{guild,channel,user}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-view").build(origin,{guild,channel,user}))
}else if (scope == "get"){
const data = instance.options.getUser("user",true)
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-get").build(source,{guild,channel,user,data}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-get").build(origin,{guild,channel,user,data}))
}else if (scope == "add"){
const data = instance.options.getUser("user",true)
@@ -46,15 +46,15 @@ export const registerCommandResponders = async () => {
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
{key:"channelid",value:channel.id,hidden:true},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"reason",value:reason ?? "/"}
])
//manage stats
- await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:users-blacklisted",1,"increase")
- await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:users-blacklisted",user.id,1,"increase")
+ await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:users-blacklisted",1,"increase")
+ await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:users-blacklisted",user.id,1,"increase")
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-add").build(source,{guild,channel,user,data,reason}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-add").build(origin,{guild,channel,user,data,reason}))
}else if (scope == "remove"){
const data = instance.options.getUser("user",true)
@@ -65,14 +65,14 @@ export const registerCommandResponders = async () => {
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
{key:"channelid",value:channel.id,hidden:true},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"reason",value:reason ?? "/"}
])
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-remove").build(source,{guild,channel,user,data,reason}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-remove").build(origin,{guild,channel,user,data,reason}))
}
}),
- new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
if (!guild) return
@@ -83,21 +83,21 @@ export const registerCommandResponders = async () => {
const reason = instance.options.getString("reason",false)
//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")
- if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-logs").build(source,{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
- if (generalConfig.data.system.messages.blacklisting.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:blacklist-dm").build(source,{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,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
opendiscord.log(instance.user.displayName+" used the 'blacklist "+scope+"' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/claim.ts b/src/commands/claim.ts
index 72c2b6c..555e573 100644
--- a/src/commands/claim.ts
+++ b/src/commands/claim.ts
@@ -1,119 +1,235 @@
///////////////////////////////////////
//CLAIM COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//CLAIM COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:claim",generalConfig.data.prefix,"claim"))
opendiscord.responders.commands.get("opendiscord:claim").workers.add([
- new api.ODWorker("opendiscord:claim",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:claim",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.claim,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when already claimed
- if (ticket.get("opendiscord:claimed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const claimUser = instance.options.getUser("user",false) ?? user
- const reason = instance.options.getString("reason",false)
-
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"claim")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketUnclaimed = await openticketUtils.replyTicketMustBeUnclaimed(instance,origin,ticket)
+ if (!isTicketUnclaimed) return cancel()
+
//start claiming ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:claim-ticket").run(source,{guild,channel,user:claimUser,ticket,reason,sendMessage:false})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(source,{guild,channel,user:claimUser,ticket,reason}))
+ const reason = instance.options.getString("reason",false)
+ const claimUser = instance.options.getUser("user",false) ?? user
+ await opendiscord.actions.get("opendiscord:claim-ticket").run(origin,{guild,channel,user:claimUser,ticket,reason,sendMessage:false})
+
+ //send message & set state
+ const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(origin,{guild,channel,user:claimUser,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"claim-message",
+ messageOrigin:origin,
+ messageAuthor:claimUser.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'claim' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//CLAIM TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:claim-ticket",/^od:claim-ticket/))
opendiscord.responders.buttons.get("opendiscord:claim-ticket").workers.add(
- new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => {
- const originalSource = instance.interaction.customId.split("_")[1] as Exclude
+ new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,user,message} = instance
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"claim")
+ if (!hasPerms) return cancel()
- if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").activate(instance)
- else if (originalSource == "unclaim-message") await opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").activate(instance)
- else await instance.defer("update",false)
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/claim")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketUnclaimed = await openticketUtils.replyTicketMustBeUnclaimed(instance,origin,ticket)
+ if (!isTicketUnclaimed) return cancel()
+
+ //fetch state details
+ const verifybar = opendiscord.verifybars.get("opendiscord:claim-ticket")
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //send verifybar
+ if (generalConfig.data.ticketSystem.disableVerifyBars){
+ //verifybar disabled, directly run response
+ await verifybar.activate(instance,"accept")
+
+ }else if (originalMsgType == "ticket-message"){
+ //ticket message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:claim-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "unclaim-message"){
+ //unclaim message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:claim-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:unclaim-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
})
)
}
-export const registerModalResponders = async () => {
- //CLAIM WITH REASON MODAL RESPONDER
- opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:claim-ticket-reason",/^od:claim-ticket-reason_/))
- opendiscord.responders.modals.get("opendiscord:claim-ticket-reason").workers.add([
- new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!channel) return
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
-
- const originalSource = instance.interaction.customId.split("_")[2] as Exclude
- const reason = instance.values.getTextField("reason",true)
-
- //claim with reason
- if (originalSource == "ticket-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }else if (originalSource == "unclaim-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason}))
- }else{
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
- }
+export async function registerVerifyBars(){
+ //CLAIM TICKET
+ opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:claim-ticket"))
+ opendiscord.verifybars.get("opendiscord:claim-ticket").workers.add([
+ new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,origin,cancel) => {
+ const {user,member,channel,guild,message} = instance
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"claim")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/claim")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketUnclaimed = await openticketUtils.replyTicketMustBeUnclaimed(instance,origin,ticket)
+ if (!isTicketUnclaimed) return cancel()
+
+ //fetch state details
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //start claiming ticket
+ if (params.selectedButtonId == "cancel"){
+ //CANCEL
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "unclaim-message"){
+ //unclaim message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
+ }else if (params.selectedButtonId == "accept"){
+ //CLAIM TICKET
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:claim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "unclaim-message"){
+ //converted to claim message
+ await opendiscord.actions.get("opendiscord:claim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"claim-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:null
+ },sentMsg.ephemeral)
+ }
+ }else if (params.selectedButtonId == "accept-with-reason"){
+ //CLAIM WITH REASON (MODAL)
+ instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:claim-ticket-reason").build("other",{guild,channel,user,ticket,message}))
+ }
+ })
+ ])
+}
+
+export async function registerModalResponders(){
+ //CLAIM WITH REASON MODAL RESPONDER
+ opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:claim-ticket-reason",/^od:claim-ticket-reason\|([^|]+)\|([^|]+)/))
+ opendiscord.responders.modals.get("opendiscord:claim-ticket-reason").workers.add([
+ new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,origin,cancel) => {
+ const {guild,user} = instance
+
+ const match = /^od:claim-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
+ if (!match) return cancel()
+ const channel = await opendiscord.client.fetchTextChannel(match[1])
+ const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"claim")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/claim")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketUnclaimed = await openticketUtils.replyTicketMustBeUnclaimed(instance,origin,ticket)
+ if (!isTicketUnclaimed) return cancel()
+
+ //fetch state details
+ const reason = instance.values.getTextField("reason",true)
+ const originalMsgOrigin = state.data.messageOrigin
+ const originalMsgType = state.data.messageType
+
+ //start claiming ticket
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:claim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
+
+ }else if (originalMsgType == "unclaim-message"){
+ //converted to claim message
+ await opendiscord.actions.get("opendiscord:claim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"claim-message",
+ messageOrigin:originalMsgOrigin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
+ }
})
])
}
\ No newline at end of file
diff --git a/src/commands/clear.ts b/src/commands/clear.ts
index 1de6e25..06093d9 100644
--- a/src/commands/clear.ts
+++ b/src/commands/clear.ts
@@ -1,35 +1,31 @@
///////////////////////////////////////
//CLEAR COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const clearMsgState = opendiscord.states.get("opendiscord:clear-message")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//CLEAR COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:clear",generalConfig.data.prefix,"clear"))
opendiscord.responders.commands.get("opendiscord:clear").workers.add([
- new api.ODWorker("opendiscord:clear",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:clear",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
-
+
+ //responder checks
//check permissions (only allow global admins: ticket admins aren't allowed to clear tickets)
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.clear,"support",user,member,channel,guild,{allowChannelUserScope:false,allowChannelRoleScope:false})
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"clear",{allowChannelUserScope:false,allowChannelRoleScope:false})
+ if (!hasPerms) return cancel()
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ //fetch data
const tempFilter = instance.options.getString("filter",false)
const filter = (tempFilter) ? tempFilter.toLowerCase() as api.ODTicketClearFilter : "all"
- const list: string[] = []
+ const channelNameList: string[] = []
const ticketList = opendiscord.tickets.getAll().filter((ticket) => {
if (filter == "all") return true
else if (filter == "open" && ticket.get("opendiscord:open").value) return true
@@ -43,46 +39,70 @@ export const registerCommandResponders = async () => {
})
for (const ticket of ticketList){
const ticketChannel = await opendiscord.tickets.getTicketChannel(ticket)
- if (ticketChannel) list.push("#"+ticketChannel.name)
+ if (ticketChannel) channelNameList.push("#"+ticketChannel.name)
}
//reply with clear verify
await instance.defer(true)
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:clear-verify-message").build(source,{guild,channel,user,filter,list}))
+ const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:clear-verify-message").build(origin,{guild,channel,user,filter,list:channelNameList,inProgress:false}))
+ if (sentMsg.success) await clearMsgState.setMsgState({channel,message:sentMsg.message,user},{
+ messageOrigin:origin,
+ clearFilter:filter,
+ clearChannelNameList:channelNameList
+ },sentMsg.ephemeral)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'clear' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//CLEAR CONTINUE BUTTON RESPONDER
- opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:clear-continue",/^od:clear-continue_/))
+ opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:clear-continue","od:clear-continue"))
opendiscord.responders.buttons.get("opendiscord:clear-continue").workers.add(
- new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!guild || channel.isDMBased()) return
- const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:clear-tickets"]["source"]
- const filter = instance.interaction.customId.split("_")[2] as api.ODTicketClearFilter
+ new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,user,message} = instance
+
+ //check message state
+ const state = await clearMsgState.getMsgState({channel,message,user})
+ if (!state){
+ //TODO TRANSLATION!!!
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"This interaction is no longer valid or has expired. Use the command `{0}` instead. It is normal to receive this error after a major Open Ticket update.".replace("{0}","/clear"),layout:"simple",customTitle:"Message State Expired"}))
+ return cancel()
+ }
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"clear")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
+
+ //fetch state details
+ const originalUser = ((state.userId) ? await opendiscord.client.fetchUser(state.userId) : user) ?? user
+ const originalOrigin = state.data.messageOrigin
+ const originalClearFilter = state.data.clearFilter
+ const originalClearChannelNameList = state.data.clearChannelNameList
//start ticket clear
- await instance.defer("update",true)
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:clear-verify-message").build(originalOrigin,{guild,channel,user:originalUser,filter:originalClearFilter,list:originalClearChannelNameList,inProgress:true}))
+
const list: string[] = []
const ticketList = opendiscord.tickets.getAll().filter((ticket) => {
- if (filter == "all") return true
- else if (filter == "open" && ticket.get("opendiscord:open").value) return true
- else if (filter == "closed" && ticket.get("opendiscord:closed").value) return true
- else if (filter == "claimed" && ticket.get("opendiscord:claimed").value) return true
- else if (filter == "pinned" && ticket.get("opendiscord:pinned").value) return true
- else if (filter == "unclaimed" && !ticket.get("opendiscord:claimed").value) return true
- else if (filter == "unpinned" && !ticket.get("opendiscord:pinned").value) return true
- else if (filter == "autoclosed" && ticket.get("opendiscord:closed").value) return true
+ if (originalClearFilter == "all") return true
+ else if (originalClearFilter == "open" && ticket.get("opendiscord:open").value) return true
+ else if (originalClearFilter == "closed" && ticket.get("opendiscord:closed").value) return true
+ else if (originalClearFilter == "claimed" && ticket.get("opendiscord:claimed").value) return true
+ else if (originalClearFilter == "pinned" && ticket.get("opendiscord:pinned").value) return true
+ else if (originalClearFilter == "unclaimed" && !ticket.get("opendiscord:claimed").value) return true
+ else if (originalClearFilter == "unpinned" && !ticket.get("opendiscord:pinned").value) return true
+ else if (originalClearFilter == "autoclosed" && ticket.get("opendiscord:closed").value) return true
else return false
})
for (const ticket of ticketList){
@@ -90,8 +110,8 @@ export const registerButtonResponders = async () => {
if (ticketChannel) list.push("#"+ticketChannel.name)
}
- await opendiscord.actions.get("opendiscord:clear-tickets").run(originalSource,{guild,channel,user,filter,list:ticketList})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:clear-message").build(originalSource,{guild,channel,user,filter,list}))
+ await opendiscord.actions.get("opendiscord:clear-tickets").run(originalOrigin,{guild,channel,user,filter:originalClearFilter,list:ticketList})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:clear-message").build(originalOrigin,{guild,channel,user,filter:originalClearFilter,list}))
})
)
}
\ No newline at end of file
diff --git a/src/commands/close.ts b/src/commands/close.ts
index 8f2c01b..64f9595 100644
--- a/src/commands/close.ts
+++ b/src/commands/close.ts
@@ -1,131 +1,243 @@
///////////////////////////////////////
//CLOSE COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//CLOSE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:close",generalConfig.data.prefix,"close"))
opendiscord.responders.commands.get("opendiscord:close").workers.add([
- new api.ODWorker("opendiscord:close",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:close",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.close,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when already closed
- if (ticket.get("opendiscord:closed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when not allowed because of missing messages
- if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
- const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
- if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"close")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
+ if (!isTicketOpen) return cancel()
+
+ const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"close")
+ if (!messagesHaveBeenSent) return cancel()
//start closing ticket
await instance.defer(false)
const reason = instance.options.getString("reason",false)
- await opendiscord.actions.get("opendiscord:close-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(source,{guild,channel,user,ticket,reason}))
+ await opendiscord.actions.get("opendiscord:close-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
+
+ //send message & set state
+ const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"close-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'close' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//CLOSE TICKET BUTTON RESPONDER
- opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:close-ticket",/^od:close-ticket_/))
+ opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:close-ticket",/^od:close-ticket/))
opendiscord.responders.buttons.get("opendiscord:close-ticket").workers.add(
- new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => {
- const originalSource = instance.interaction.customId.split("_")[1] as Exclude
+ new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,message,user,member} = instance
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"close")
+ if (!hasPerms) return cancel()
- if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").activate(instance)
- else if (originalSource == "reopen-message") await opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").activate(instance)
- else await instance.defer("update",false)
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/close")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
+ if (!isTicketOpen) return cancel()
+
+ const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"close")
+ if (!messagesHaveBeenSent) return cancel()
+
+ //fetch state details
+ const verifybar = opendiscord.verifybars.get("opendiscord:close-ticket")
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //send verifybar
+ if (generalConfig.data.ticketSystem.disableVerifyBars){
+ //verifybar disabled, directly run response
+ await verifybar.activate(instance,"accept")
+
+ }else if (originalMsgType == "ticket-message"){
+ //ticket message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:close-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "reopen-message"){
+ //reopen message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:close-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:reopen-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
})
)
}
-export const registerModalResponders = async () => {
- //CLOSE WITH REASON MODAL RESPONDER
- opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:close-ticket-reason",/^od:close-ticket-reason_/))
- opendiscord.responders.modals.get("opendiscord:close-ticket-reason").workers.add([
- new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!channel) return
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
+export async function registerVerifyBars(){
+ //CLOSE TICKET VERIFYBAR
+ opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:close-ticket"))
+ opendiscord.verifybars.get("opendiscord:close-ticket").workers.add([
+ new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,origin,cancel) => {
+ const {user,member,channel,guild,message} = instance
- const originalSource = instance.interaction.customId.split("_")[2] as Exclude
- const reason = instance.values.getTextField("reason",true)
-
- //close with reason
- if (originalSource == "ticket-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }else if (originalSource == "reopen-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason}))
- }else{
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"close")
+ if (!hasPerms) return cancel()
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/close")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
+ if (!isTicketOpen) return cancel()
+
+ const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"close")
+ if (!messagesHaveBeenSent) return cancel()
+
+ //fetch state details
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //start closing ticket
+ if (params.selectedButtonId == "cancel"){
+ //CANCEL
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "reopen-message"){
+ //reopen message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
+ }else if (params.selectedButtonId == "accept"){
+ //CLOSE TICKET
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:close-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "reopen-message"){
+ //converted to close message
+ await opendiscord.actions.get("opendiscord:close-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"close-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:null
+ },sentMsg.ephemeral)
+ }
+ }else if (params.selectedButtonId == "accept-with-reason"){
+ //CLOSE WITH REASON (MODAL)
+ instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:close-ticket-reason").build("other",{guild,channel,user,ticket,message}))
+ }
+ })
+ ])
+}
+
+export async function registerModalResponders(){
+ //CLOSE WITH REASON MODAL RESPONDER
+ opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:close-ticket-reason",/^od:close-ticket-reason\|([^|]+)\|([^|]+)/))
+ opendiscord.responders.modals.get("opendiscord:close-ticket-reason").workers.add([
+ new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,origin,cancel) => {
+ const {guild,user} = instance
+
+ const match = /^od:close-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
+ if (!match) return cancel()
+ const channel = await opendiscord.client.fetchTextChannel(match[1])
+ const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"close")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/close")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
+ if (!isTicketOpen) return cancel()
+
+ //fetch state details
+ const reason = instance.values.getTextField("reason",true)
+ const originalMsgOrigin = state.data.messageOrigin
+ const originalMsgType = state.data.messageType
+
+ //start closing ticket
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:close-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
+
+ }else if (originalMsgType == "reopen-message"){
+ //converted to close message
+ await opendiscord.actions.get("opendiscord:close-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"close-message",
+ messageOrigin:originalMsgOrigin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
+ }
})
])
}
\ No newline at end of file
diff --git a/src/commands/delete.ts b/src/commands/delete.ts
index ebe4c32..8c153a8 100644
--- a/src/commands/delete.ts
+++ b/src/commands/delete.ts
@@ -1,64 +1,42 @@
///////////////////////////////////////
//DELETE COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//DELETE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:delete",generalConfig.data.prefix,"delete"))
opendiscord.responders.commands.get("opendiscord:delete").workers.add([
- new api.ODWorker("opendiscord:delete",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:delete",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
+ if (!hasPerms) return cancel()
- //return when not allowed because of missing messages
- if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
- const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
- if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
- return cancel()
- }
- }
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
+ if (!isTicketOpen) return cancel()
- const reason = instance.options.getString("reason",false)
- const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false
+ const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"delete")
+ if (!messagesHaveBeenSent) return cancel()
//don't allow deleteWithoutTranscript to non-global-admins when enabled
- if (withoutTranscript && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){
+ const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false
+ 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}))){
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()
@@ -67,84 +45,227 @@ export const registerCommandResponders = async () => {
//start deleting ticket
await instance.defer(false)
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(source,{guild,channel,user,ticket,reason}))
- await opendiscord.actions.get("opendiscord:delete-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript})
+ const reason = instance.options.getString("reason",false)
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(origin,{guild,channel,user,ticket,reason}))
+ await opendiscord.actions.get("opendiscord:delete-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript})
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'delete' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//DELETE TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:delete-ticket",/^od:delete-ticket/))
opendiscord.responders.buttons.get("opendiscord:delete-ticket").workers.add(
- new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
- const originalSource = instance.interaction.customId.split("_")[1] as Exclude
+ new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,message,user,member} = instance
- if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").activate(instance)
- else if (originalSource == "close-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").activate(instance)
- else if (originalSource == "reopen-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").activate(instance)
- else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").activate(instance)
- else await instance.defer("update",false)
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/delete")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"delete")
+ if (!messagesHaveBeenSent) return cancel()
+
+ //fetch state details
+ const verifybar = opendiscord.verifybars.get("opendiscord:delete-ticket")
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //send verifybar
+ if (generalConfig.data.ticketSystem.disableVerifyBars){
+ //verifybar disabled, directly run response
+ await verifybar.activate(instance,"accept")
+
+ }else if (originalMsgType == "ticket-message"){
+ //ticket message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:delete-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "close-message"){
+ //close message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:delete-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:close-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }else if (originalMsgType == "reopen-message"){
+ //reopen message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:delete-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:reopen-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }else if (originalMsgType == "autoclose-message"){
+ //autoclose message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:delete-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:autoclose-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket}))
+ }
})
)
}
-export const registerModalResponders = async () => {
- //REOPEN WITH REASON MODAL RESPONDER
- opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:delete-ticket-reason",/^od:delete-ticket-reason_/))
+export async function registerVerifyBars(){
+ //DELETE TICKET
+ opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket"))
+ opendiscord.verifybars.get("opendiscord:delete-ticket").workers.add([
+ new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin,cancel) => {
+ const {user,member,channel,guild,message} = instance
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/delete")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"delete")
+ if (!messagesHaveBeenSent) return cancel()
+
+ //don't allow deleteWithoutTranscript to non-global-admins when enabled
+ const withoutTranscript = (params.selectedButtonId == "accept-without-transcript")
+ 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}))){
+ 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()
+ }
+ }
+
+ //fetch state details
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //start deleting ticket
+ if (params.selectedButtonId == "cancel"){
+ //CANCEL
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "close-message"){
+ //close message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }else if (originalMsgType == "reopen-message"){
+ //reopen message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }else if (originalMsgType == "autoclose-message"){
+ //autoclose message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("verifybar",{guild,channel,user:originalUser,ticket}))
+ }
+ }else if (params.selectedButtonId == "accept" || params.selectedButtonId == "accept-without-transcript"){
+ //DELETE TICKET
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript})
+ ticket.get("opendiscord:for-deletion").value = true //disable ticket message buttons
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
+
+ }else if (originalMsgType == "close-message"){
+ //converted to delete message
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason:null}))
+
+ }else if (originalMsgType == "reopen-message"){
+ //converted to delete message
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason:null}))
+
+ }else if (originalMsgType == "autoclose-message"){
+ //converted to delete message
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason:null}))
+
+ }
+ }else if (params.selectedButtonId == "accept-with-reason"){
+ //DELETE WITH REASON (MODAL)
+ instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("other",{guild,channel,user,ticket,message}))
+ }
+ })
+ ])
+}
+
+export async function registerModalResponders(){
+ //DELETE WITH REASON MODAL RESPONDER
+ opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:delete-ticket-reason",/^od:delete-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:delete-ticket-reason").workers.add([
- new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!channel) return
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
+ new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,origin,cancel) => {
+ const {guild,user} = instance
- const originalSource = instance.interaction.customId.split("_")[2] as Exclude
+ const match = /^od:delete-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
+ if (!match) return cancel()
+ const channel = await opendiscord.client.fetchTextChannel(match[1])
+ const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/delete")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ //fetch state details
const reason = instance.values.getTextField("reason",true)
+ const originalMsgOrigin = state.data.messageOrigin
+ const originalMsgType = state.data.messageType
- //delete with reason
- if (originalSource == "ticket-message"){
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false})
- //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
- ticket.get("opendiscord:for-deletion").value = true
+ //start deleting ticket
+ //don't await DELETE action => else it will update the message after the channel has been deleted
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false})
+ ticket.get("opendiscord:for-deletion").value = true //disable ticket message buttons
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }else if (originalSource == "close-message"){
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason}))
- }else if (originalSource == "reopen-message"){
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason}))
- }else if (originalSource == "autoclose-message"){
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason}))
- }else{
- await instance.defer("update",false)
- //don't await DELETE action => else it will update the message after the channel has been deleted
- opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false})
+
+ }else if (originalMsgType == "close-message"){
+ //converted to delete message
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+
+ }else if (originalMsgType == "reopen-message"){
+ //converted to delete message
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+
+ }else if (originalMsgType == "autoclose-message"){
+ //converted to delete message
+ opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+
}
})
])
diff --git a/src/commands/help.ts b/src/commands/help.ts
index a8eb799..1ad49a2 100644
--- a/src/commands/help.ts
+++ b/src/commands/help.ts
@@ -1,50 +1,46 @@
///////////////////////////////////////
//HELP COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//HELP COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:help",generalConfig.data.prefix,"help"))
opendiscord.responders.commands.get("opendiscord:help").workers.add([
- new api.ODWorker("opendiscord:help",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:help",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.help,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"help")
+ if (!hasPerms) return cancel()
//calculate slash/text mode for help menu
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 mode = "slash"
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:help-menu").build(source,{mode,page:0}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:help-menu").build(origin,{mode,page:0}))
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'help' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//HELP MENU SWITCH BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-switch",/^od:help-menu-switch_(slash|text)/))
opendiscord.responders.buttons.get("opendiscord:help-menu-switch").workers.add(
- new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,origin,cancel) => {
const mode = instance.interaction.customId.split("_")[1] as "slash"|"text"
const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/)
const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0
@@ -59,7 +55,7 @@ export const registerButtonResponders = async () => {
//HELP MENU PREVIOUS BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-previous",/^od:help-menu-previous/))
opendiscord.responders.buttons.get("opendiscord:help-menu-previous").workers.add(
- new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,origin,cancel) => {
const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/)
const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/)
const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0
@@ -73,7 +69,7 @@ export const registerButtonResponders = async () => {
//HELP MENU NEXT BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-next",/^od:help-menu-next/))
opendiscord.responders.buttons.get("opendiscord:help-menu-next").workers.add(
- new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,origin,cancel) => {
const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/)
const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/)
const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0
diff --git a/src/commands/move.ts b/src/commands/move.ts
index 93ad8ed..3ec418f 100644
--- a/src/commands/move.ts
+++ b/src/commands/move.ts
@@ -1,48 +1,36 @@
///////////////////////////////////////
//MOVE COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//MOVE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:move",generalConfig.data.prefix,"move"))
opendiscord.responders.commands.get("opendiscord:move").workers.add([
- new api.ODWorker("opendiscord:move",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:move",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.move,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check if in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"move")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+ //fetch data
const id = instance.options.getString("id",true)
const reason = instance.options.getString("reason",false)
-
const option = opendiscord.options.get(id)
+
//return if unknown option
if (!option || !(option instanceof api.ODTicketOption)){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.titles.unknownOption"),layout:"simple"}))
@@ -56,15 +44,15 @@ export const registerCommandResponders = async () => {
//start moving ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:move-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:option})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(source,{guild,channel,user,ticket,reason,data:option}))
+ await opendiscord.actions.get("opendiscord:move-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,data:option})
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(origin,{guild,channel,user,ticket,reason,data:option}))
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'move' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/panel.ts b/src/commands/panel.ts
index cb84407..ff5356d 100644
--- a/src/commands/panel.ts
+++ b/src/commands/panel.ts
@@ -1,42 +1,41 @@
///////////////////////////////////////
//STATS COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//PANEL COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:panel",generalConfig.data.prefix,/^panel/))
opendiscord.responders.commands.get("opendiscord:panel").workers.add([
- new api.ODWorker("opendiscord:panel",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:panel",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.panel,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild || instance.channel.type == discord.ChannelType.GroupDM){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
- return cancel()
- }
- //get panel data
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"panel")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ //fetch data
const id = instance.options.getString("id",true)
const panel = opendiscord.panels.get(id)
if (!panel){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-panel-unknown").build(source,{guild,channel,user}))
+ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-panel-unknown").build(origin,{guild,channel,user}))
return cancel()
}
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:panel-ready").build(source,{guild,channel,user,panel}))
- const panelMessage = await instance.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:panel").build(source,{guild,channel,user,panel})).message)
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:panel-ready").build(origin,{guild,channel,user,panel}))
+ const panelMessage = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:panel").build(origin,{guild,channel,user,panel})).message)
//add panel to database (this way, the bot knows where all panels are located)
const globalDatabase = opendiscord.databases.get("opendiscord:global")
@@ -47,12 +46,12 @@ export const registerCommandResponders = async () => {
await globalDatabase.set("opendiscord:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value)
}
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'panel' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/pin.ts b/src/commands/pin.ts
index f1a8499..8ca9fc0 100644
--- a/src/commands/pin.ts
+++ b/src/commands/pin.ts
@@ -1,151 +1,235 @@
///////////////////////////////////////
//PIN COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//PIN COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:pin",generalConfig.data.prefix,"pin"))
opendiscord.responders.commands.get("opendiscord:pin").workers.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.pin
-
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]}))
- return cancel()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:pin",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:pin",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.pin,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when already pinned
- if (ticket.get("opendiscord:pinned").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"pin")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketUnpinned = await openticketUtils.replyTicketMustBeUnpinned(instance,origin,ticket)
+ if (!isTicketUnpinned) return cancel()
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const reason = instance.options.getString("reason",false)
-
//start pinning ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:pin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(source,{guild,channel,user,ticket,reason}))
+ const reason = instance.options.getString("reason",false)
+ await opendiscord.actions.get("opendiscord:pin-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
+
+ //send message & set state
+ const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"pin-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'pin' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//PIN TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:pin-ticket",/^od:pin-ticket/))
opendiscord.responders.buttons.get("opendiscord:pin-ticket").workers.add(
- new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => {
- const originalSource = instance.interaction.customId.split("_")[1] as Exclude
+ new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,user,message} = instance
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"pin")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
- if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").activate(instance)
- else if (originalSource == "unpin-message") await opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").activate(instance)
- else await instance.defer("update",false)
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/pin")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketUnpinned = await openticketUtils.replyTicketMustBeUnpinned(instance,origin,ticket)
+ if (!isTicketUnpinned) return cancel()
+
+ //fetch state details
+ const verifybar = opendiscord.verifybars.get("opendiscord:pin-ticket")
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //send verifybar
+ if (generalConfig.data.ticketSystem.disableVerifyBars){
+ //verifybar disabled, directly run response
+ await verifybar.activate(instance,"accept")
+
+ }else if (originalMsgType == "ticket-message"){
+ //ticket message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:pin-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "unpin-message"){
+ //unpin message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:pin-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:unpin-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
})
)
}
-export const registerModalResponders = async () => {
- //PIN WITH REASON MODAL RESPONDER
- opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:pin-ticket-reason",/^od:pin-ticket-reason_/))
- opendiscord.responders.modals.get("opendiscord:pin-ticket-reason").workers.add([
- new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!channel) return
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
- const originalSource = instance.interaction.customId.split("_")[2] as Exclude
- const reason = instance.values.getTextField("reason",true)
-
- //pin with reason
- if (originalSource == "ticket-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }else if (originalSource == "unpin-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason}))
- }else{
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
- }
+export async function registerVerifyBars(){
+ //PIN TICKET
+ opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:pin-ticket"))
+ opendiscord.verifybars.get("opendiscord:pin-ticket").workers.add([
+ new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,origin,cancel) => {
+ const {user,member,channel,guild,message} = instance
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"pin")
+ if (!hasPerms) return cancel()
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/pin")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketUnpinned = await openticketUtils.replyTicketMustBeUnpinned(instance,origin,ticket)
+ if (!isTicketUnpinned) return cancel()
+
+ //fetch state details
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //start pinning ticket
+ if (params.selectedButtonId == "cancel"){
+ //CANCEL
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "unpin-message"){
+ //unpin message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
+ }else if (params.selectedButtonId == "accept"){
+ //PIN TICKET
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:pin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "unpin-message"){
+ //converted to pin message
+ await opendiscord.actions.get("opendiscord:pin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"pin-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:null
+ },sentMsg.ephemeral)
+ }
+ }else if (params.selectedButtonId == "accept-with-reason"){
+ //PIN WITH REASON (MODAL)
+ instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:pin-ticket-reason").build("other",{guild,channel,user,ticket,message}))
+ }
+ })
+ ])
+}
+
+export async function registerModalResponders(){
+ //PIN WITH REASON MODAL RESPONDER
+ opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:pin-ticket-reason",/^od:pin-ticket-reason\|([^|]+)\|([^|]+)/))
+ opendiscord.responders.modals.get("opendiscord:pin-ticket-reason").workers.add([
+ new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,origin,cancel) => {
+ const {guild,user} = instance
+
+ const match = /^od:pin-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
+ if (!match) return cancel()
+ const channel = await opendiscord.client.fetchTextChannel(match[1])
+ const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"pin")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/pin")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketUnpinned = await openticketUtils.replyTicketMustBeUnpinned(instance,origin,ticket)
+ if (!isTicketUnpinned) return cancel()
+
+ //fetch state details
+ const reason = instance.values.getTextField("reason",true)
+ const originalMsgOrigin = state.data.messageOrigin
+ const originalMsgType = state.data.messageType
+
+ //start pinning ticket
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:pin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
+
+ }else if (originalMsgType == "unpin-message"){
+ //converted to pin message
+ await opendiscord.actions.get("opendiscord:pin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"pin-message",
+ messageOrigin:originalMsgOrigin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
+ }
})
])
}
\ No newline at end of file
diff --git a/src/commands/priority.ts b/src/commands/priority.ts
index 39812ca..2125e41 100644
--- a/src/commands/priority.ts
+++ b/src/commands/priority.ts
@@ -1,44 +1,30 @@
///////////////////////////////////////
//PRIORITY COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//PRIORITY COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:priority",generalConfig.data.prefix,"priority"))
opendiscord.responders.commands.get("opendiscord:priority").workers.add([
- new api.ODWorker("opendiscord:priority",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:priority",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.priority,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"priority")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
@@ -56,21 +42,21 @@ export const registerCommandResponders = async () => {
//start changing ticket priority
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:update-ticket-priority").run(source,{guild,channel,user,ticket,newPriority:priority,sendMessage:false,reason})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:priority-set").build(source,{guild,channel,user,ticket,priority,reason}))
+ await opendiscord.actions.get("opendiscord:update-ticket-priority").run(origin,{guild,channel,user,ticket,newPriority:priority,sendMessage:false,reason})
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:priority-set").build(origin,{guild,channel,user,ticket,priority,reason}))
}else if (scope == "get"){
const priority = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value)
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:priority-get").build(source,{guild,channel,user,ticket,priority}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:priority-get").build(origin,{guild,channel,user,ticket,priority}))
}
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
opendiscord.log(instance.user.displayName+" used the 'priority "+scope+"' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/remove.ts b/src/commands/remove.ts
index c6ec472..554178d 100644
--- a/src/commands/remove.ts
+++ b/src/commands/remove.ts
@@ -1,45 +1,32 @@
///////////////////////////////////////
//REMOVE COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//REMOVE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:remove",generalConfig.data.prefix,"remove"))
opendiscord.responders.commands.get("opendiscord:remove").workers.add([
- new api.ODWorker("opendiscord:remove",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:remove",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.remove,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"remove")
+ if (!hasPerms) return cancel()
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+ //fetch data
const data = instance.options.getUser("user",true)
const reason = instance.options.getString("reason",false)
@@ -52,15 +39,15 @@ export const registerCommandResponders = async () => {
//start removing user from ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:remove-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(source,{guild,channel,user,ticket,reason,data}))
+ await opendiscord.actions.get("opendiscord:remove-ticket-user").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,data})
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(origin,{guild,channel,user,ticket,reason,data}))
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'remove' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/rename.ts b/src/commands/rename.ts
index 7bbee26..6b2dee6 100644
--- a/src/commands/rename.ts
+++ b/src/commands/rename.ts
@@ -1,59 +1,46 @@
///////////////////////////////////////
//RENAME COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//RENAME COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:rename",generalConfig.data.prefix,"rename"))
opendiscord.responders.commands.get("opendiscord:rename").workers.add([
- new api.ODWorker("opendiscord:rename",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:rename",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.rename,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"rename")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+ //fetch data
const name = instance.options.getString("name",true)
const reason = instance.options.getString("reason",false)
//start renaming ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:rename-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:name})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(source,{guild,channel,user,ticket,reason,data:name}))
+ await opendiscord.actions.get("opendiscord:rename-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,data:name})
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(origin,{guild,channel,user,ticket,reason,data:name}))
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'rename' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/reopen.ts b/src/commands/reopen.ts
index fb86a30..2ba0772 100644
--- a/src/commands/reopen.ts
+++ b/src/commands/reopen.ts
@@ -1,123 +1,261 @@
///////////////////////////////////////
//REOPEN COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//REOPEN COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:reopen",generalConfig.data.prefix,"reopen"))
opendiscord.responders.commands.get("opendiscord:reopen").workers.add([
- new api.ODWorker("opendiscord:reopen",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:reopen",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.reopen,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when not closed
- if (!ticket.get("opendiscord:closed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const reason = instance.options.getString("reason",false)
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"reopen")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketClosed = await openticketUtils.replyTicketMustBeClosed(instance,origin,ticket)
+ if (!isTicketClosed) return cancel()
//start reopening ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:reopen-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(source,{guild,channel,user,ticket,reason}))
+ const reason = instance.options.getString("reason",false)
+ await opendiscord.actions.get("opendiscord:reopen-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
+
+ //send message & set state
+ const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"reopen-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'reopen' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//REOPEN TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:reopen-ticket",/^od:reopen-ticket/))
opendiscord.responders.buttons.get("opendiscord:reopen-ticket").workers.add(
- new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => {
- const originalSource = instance.interaction.customId.split("_")[1] as Exclude
+ new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,message,user,member} = instance
- if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").activate(instance)
- else if (originalSource == "close-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").activate(instance)
- else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").activate(instance)
- else await instance.defer("update",false)
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"reopen")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/reopen")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketClosed = await openticketUtils.replyTicketMustBeClosed(instance,origin,ticket)
+ if (!isTicketClosed) return cancel()
+
+ //fetch state details
+ const verifybar = opendiscord.verifybars.get("opendiscord:reopen-ticket")
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //send verifybar
+ if (generalConfig.data.ticketSystem.disableVerifyBars){
+ //verifybar disabled, directly run response
+ await verifybar.activate(instance,"accept")
+
+ }else if (originalMsgType == "ticket-message"){
+ //ticket message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:reopen-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "close-message"){
+ //close message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:reopen-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:close-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }else if (originalMsgType == "autoclose-message"){
+ //autoclose message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:reopen-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:autoclose-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket}))
+ }
})
)
}
-export const registerModalResponders = async () => {
- //REOPEN WITH REASON MODAL RESPONDER
- opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:reopen-ticket-reason",/^od:reopen-ticket-reason_/))
- opendiscord.responders.modals.get("opendiscord:reopen-ticket-reason").workers.add([
- new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!channel) return
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
-
- const originalSource = instance.interaction.customId.split("_")[2] as Exclude
- const reason = instance.values.getTextField("reason",true)
-
- //reopen with reason
- if (originalSource == "ticket-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }else if (originalSource == "close-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
- }else if (originalSource == "autoclose-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
- }else{
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
- }
+export async function registerVerifyBars(){
+ //REOPEN TICKET
+ opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket"))
+ opendiscord.verifybars.get("opendiscord:reopen-ticket").workers.add([
+ new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,origin,cancel) => {
+ const {user,member,channel,guild,message} = instance
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"reopen")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/reopen")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketClosed = await openticketUtils.replyTicketMustBeClosed(instance,origin,ticket)
+ if (!isTicketClosed) return cancel()
+
+ //fetch state details
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //start reopening ticket
+ if (params.selectedButtonId == "cancel"){
+ //CANCEL
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "close-message"){
+ //close message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }else if (originalMsgType == "autoclose-message"){
+ //autoclose message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("verifybar",{guild,channel,user:originalUser,ticket}))
+ }
+ }else if (params.selectedButtonId == "accept"){
+ //REOPEN TICKET
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "close-message"){
+ //converted to reopen message
+ await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"reopen-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:null
+ },sentMsg.ephemeral)
+ }else if (originalMsgType == "autoclose-message"){
+ //converted to reopen message
+ await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"reopen-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:null
+ },sentMsg.ephemeral)
+ }
+ }else if (params.selectedButtonId == "accept-with-reason"){
+ //REOPEN WITH REASON (MODAL)
+ instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("other",{guild,channel,user,ticket,message}))
+ }
+ })
+ ])
+}
+
+export async function registerModalResponders(){
+ //REOPEN WITH REASON MODAL RESPONDER
+ opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:reopen-ticket-reason",/^od:reopen-ticket-reason\|([^|]+)\|([^|]+)/))
+ opendiscord.responders.modals.get("opendiscord:reopen-ticket-reason").workers.add([
+ new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,origin,cancel) => {
+ const {guild,user} = instance
+
+ const match = /^od:reopen-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
+ if (!match) return cancel()
+ const channel = await opendiscord.client.fetchTextChannel(match[1])
+ const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"reopen")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/reopen")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketClosed = await openticketUtils.replyTicketMustBeClosed(instance,origin,ticket)
+ if (!isTicketClosed) return cancel()
+
+ //fetch state details
+ const reason = instance.values.getTextField("reason",true)
+ const originalMsgOrigin = state.data.messageOrigin
+ const originalMsgType = state.data.messageType
+
+ //start reopening ticket
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
+
+ }else if (originalMsgType == "close-message"){
+ //converted to reopen message
+ await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"reopen-message",
+ messageOrigin:originalMsgOrigin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
+ }else if (originalMsgType == "autoclose-message"){
+ //converted to reopen message
+ await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"reopen-message",
+ messageOrigin:originalMsgOrigin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
+ }
})
])
}
\ No newline at end of file
diff --git a/src/commands/role.ts b/src/commands/role.ts
index e9de633..58dbc17 100644
--- a/src/commands/role.ts
+++ b/src/commands/role.ts
@@ -1,30 +1,28 @@
///////////////////////////////////////
//ROLE BUTTON (not command)
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//ROLE OPTION BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:role-option",/^od:role-option_/))
opendiscord.responders.buttons.get("opendiscord:role-option").workers.add(
- new api.ODWorker("opendiscord:role-option",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:role-option",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
- return cancel()
- }
+ //responder checks
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//get option data
const optionId = instance.interaction.customId.split("_")[2]
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODRoleOption)){
//error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user}))
+ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
return cancel()
}
@@ -33,10 +31,10 @@ export const registerButtonResponders = async () => {
const res = await opendiscord.actions.get("opendiscord:reaction-role").run("panel-button",{guild,user,option,overwriteMode:null})
if (!res.result || !res.role){
//error
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{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()
}
- 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}))
})
)
}
\ No newline at end of file
diff --git a/src/commands/stats.ts b/src/commands/stats.ts
index 46be1fb..d6d6da6 100644
--- a/src/commands/stats.ts
+++ b/src/commands/stats.ts
@@ -1,117 +1,58 @@
///////////////////////////////////////
//STATS COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//STATS COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:stats",generalConfig.data.prefix,/^stats/))
opendiscord.responders.commands.get("opendiscord:stats").workers.add([
- new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
- const permissionMode = generalConfig.data.system.permissions.stats
-
- //command is disabled
- if (permissionMode == "none"){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }
-
- //reset subcommand is owner/developer only
- if (instance.options.getSubCommand() == "reset"){
- if (!opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]}))
- return cancel()
- }else return
- }
-
- //permissions for normal scopes
- if (permissionMode == "everyone") return
- else if (permissionMode == "admin"){
- if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]}))
- return cancel()
- }else return
- }else{
- if (!instance.guild || !instance.member){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
- return cancel()
- }
- const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
- if (!role){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
- return cancel()
- }
- if (!role.members.has(instance.member.id)){
- //no permissions
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
- }else return
- }
- }),
- new api.ODWorker("opendiscord:stats",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:stats",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
- if (generalConfig.data.system.permissions.stats === "none"){
- //command is disabled
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
- return cancel()
-
- }else if (instance.options.getSubCommand() === "reset" && !opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
+ if (instance.options.getSubCommand() === "reset" && !opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//reset --> owner/developer role is required
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]}))
return cancel()
-
}else{
//default permissions check
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.stats,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"stats")
+ if (!hasPerms) return cancel()
}
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
- return cancel()
- }
+ //responder checks
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
if (!scope || (scope != "global" && scope != "ticket" && scope != "user" && scope != "reset")) return
if (scope == "global"){
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-global").build(source,{guild,channel,user}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-global").build(origin,{guild,channel,user}))
}else if (scope == "ticket"){
const id = instance.options.getChannel("ticket",false)?.id ?? channel.id
const ticket = opendiscord.tickets.get(id)
- if (ticket) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket").build(source,{guild,channel,user,scopeData:ticket}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket-unknown").build(source,{guild,channel,user,id}))
+ if (ticket) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket").build(origin,{guild,channel,user,scopeData:ticket}))
+ else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket-unknown").build(origin,{guild,channel,user,id}))
}else if (scope == "user"){
const statsUser = instance.options.getUser("user",false) ?? user
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-user").build(source,{guild,channel,user,scopeData:statsUser}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-user").build(origin,{guild,channel,user,scopeData:statsUser}))
}else if (scope == "reset"){
const reason = instance.options.getString("reason",false)
- opendiscord.stats.reset()
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-reset").build(source,{guild,channel,user,reason}))
-
+ opendiscord.statistics.reset()
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-reset").build(origin,{guild,channel,user,reason}))
}
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
let data: string
if (scope == "ticket"){
@@ -123,7 +64,7 @@ export const registerCommandResponders = async () => {
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source},
+ {key:"method",value:origin},
{key:"data",value:data},
])
})
diff --git a/src/commands/ticket.ts b/src/commands/ticket.ts
index ce26854..92c1c86 100644
--- a/src/commands/ticket.ts
+++ b/src/commands/ticket.ts
@@ -1,173 +1,161 @@
///////////////////////////////////////
//TICKET COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
-async function checkTicketCreationPerms(instance:api.ODButtonResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance|api.ODCommandResponderInstance,source:api.ODActionManagerIds_Default["opendiscord:create-ticket-permissions"]["source"],guild:discord.Guild,user:discord.User,option:api.ODTicketOption){
+async function checkTicketCreationPerms(instance:api.ODButtonResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance|api.ODCommandResponderInstance,origin:api.ODActionManagerIdMappings["opendiscord:create-ticket-permissions"]["origin"],guild:discord.Guild,user:discord.User,option:api.ODTicketOption){
//check ticket permissions
- const permsRes = await opendiscord.actions.get("opendiscord:create-ticket-permissions").run(source,{guild,user,option})
+ const permsRes = await opendiscord.actions.get("opendiscord:create-ticket-permissions").run(origin,{guild,user,option})
if (!permsRes.valid && instance.channel){
//error
- const newSource = (source === "slash" || source === "text") ? source : "other"
- if (permsRes.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-blacklisted").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user}))
- else if (permsRes.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-cooldown").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,until:permsRes.cooldownUntil}))
- else if (permsRes.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"}))
- else if (permsRes.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"}))
- else if (permsRes.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"}))
- else if (permsRes.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"}))
- else if (permsRes.reason == "custom") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,layout:"simple",error:permsRes.customReason ?? lang.getTranslation("errors.descriptions.unableToCreateTicket")+" `Unknown invalid_permission_reason => no reason specified by plugin`",customTitle:lang.getTranslation("errors.titles.permissionError")}))
- else instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"}))
+ const newOrigin = (origin === "slash" || origin === "text") ? origin : "other"
+ if (permsRes.reason == "blacklist") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-blacklisted").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
+ else if (permsRes.reason == "cooldown") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-cooldown").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,until:permsRes.cooldownUntil}))
+ else if (permsRes.reason == "global-limit") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"}))
+ else if (permsRes.reason == "global-user-limit") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"}))
+ else if (permsRes.reason == "option-limit") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"}))
+ else if (permsRes.reason == "option-user-limit") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"}))
+ else if (permsRes.reason == "custom") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,layout:"simple",error:permsRes.customReason ?? lang.getTranslation("errors.descriptions.unableToCreateTicket")+" `Unknown invalid_permission_reason => no reason specified by plugin`",customTitle:lang.getTranslation("errors.titles.permissionError")}))
+ else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"}))
return false
}else return true
}
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//TICKET COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:ticket",generalConfig.data.prefix,/^ticket/))
opendiscord.responders.commands.get("opendiscord:ticket").workers.add([
- new api.ODWorker("opendiscord:ticket",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.ticket,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
- return cancel()
- }
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"ticket")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//get option data
const optionId = instance.options.getString("id",true)
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODTicketOption)){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user}))
+ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
return cancel()
}
//start ticket creation
if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){
- //send modal
- instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build(source,{guild,channel,user,option}))
+ //SEND MODAL
+ instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build(origin,{guild,channel,user,option}))
}else{
- //check ticket permissions
- if (!(await checkTicketCreationPerms(instance,source,guild,user,option))) return cancel()
-
- //create ticket
+ //check ticket permissions (modals need check after submit)
+ if (!(await checkTicketCreationPerms(instance,origin,guild,user,option))) return cancel()
+
+ //CREATE TICKET
await instance.defer(true)
- const res = await opendiscord.actions.get("opendiscord:create-ticket").run(source,{guild,user,answers:[],option})
+ const res = await opendiscord.actions.get("opendiscord:create-ticket").run(origin,{guild,user,answers:[],option})
if (!res.channel || !res.ticket){
//error
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{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()
}
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(source,{guild,channel:res.channel,user,ticket:res.ticket}))
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(origin,{guild,channel:res.channel,user,ticket:res.ticket}))
}
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'ticket' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//TICKET OPTION BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:ticket-option",/^od:ticket-option_/))
opendiscord.responders.buttons.get("opendiscord:ticket-option").workers.add(
- new api.ODWorker("opendiscord:ticket-option",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:ticket-option",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
- return cancel()
- }
+
+ //responder checks
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
- //get option
+ //get option data
const optionId = instance.interaction.customId.split("_")[2]
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODTicketOption)){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user}))
+ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
return cancel()
}
//start ticket creation
if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){
- //send modal
+ //SEND MODAL
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build("panel-button",{guild,channel,user,option}))
}else{
- //check ticket permissions
+ //check ticket permissions (modals need check after submit)
if (!(await checkTicketCreationPerms(instance,"panel-button",guild,user,option))) return cancel()
-
- //create ticket
- await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
+
+ //CREATE TICKET
+ 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})
if (!res.channel || !res.ticket){
//error
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{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()
}
- 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}))
}
})
)
}
-export const registerDropdownResponders = async () => {
+export async function registerDropdownResponders(){
//PANEL DROPDOWN TICKETS DROPDOWN RESPONDER
opendiscord.responders.dropdowns.add(new api.ODDropdownResponder("opendiscord:panel-dropdown-tickets",/^od:panel-dropdown_/))
opendiscord.responders.dropdowns.get("opendiscord:panel-dropdown-tickets").workers.add(
- new api.ODWorker("opendiscord:panel-dropdown-tickets",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:panel-dropdown-tickets",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
- return cancel()
- }
+
+ //responder checks
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
- //get option
+ //get option data
const optionId = instance.values.getStringValues()[0].split("_")[2]
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODTicketOption)){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user}))
+ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
return cancel()
}
//start ticket creation
if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){
- //send modal
+ //SEND MODAL
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build("panel-dropdown",{guild,channel,user,option}))
}else{
- //check ticket permissions
+ //check ticket permissions (modals need check after submit)
if (!(await checkTicketCreationPerms(instance,"panel-dropdown",guild,user,option))) return cancel()
-
- //create ticket
- await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
+
+ //CREATE TICKET
+ 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})
if (!res.channel || !res.ticket){
//error
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{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()
}
- 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)
@@ -181,31 +169,29 @@ export const registerDropdownResponders = async () => {
)
}
-export const registerModalResponders = async () => {
+export async function registerModalResponders(){
//TICKET QUESTIONS RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:ticket-questions",/^od:ticket-questions_/))
opendiscord.responders.modals.get("opendiscord:ticket-questions").workers.add([
- new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
- await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
- if (!channel) throw new api.ODSystemError("The 'Ticket Questions' modal requires a channel for responding!")
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
- return cancel()
- }
+
+ //responder checks
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
- const originalSource = instance.interaction.customId.split("_")[2] as ("panel-button"|"panel-dropdown"|"slash"|"text"|"other")
-
- //get option
+ //get option data
const optionId = instance.interaction.customId.split("_")[1]
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODTicketOption)){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel,user:instance.user}))
+ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel,user:instance.user}))
return cancel()
}
+ //check ticket permissions (modals need check after submit)
+ const originalOrigin = instance.interaction.customId.split("_")[2] as ("panel-button"|"panel-dropdown"|"slash"|"text"|"other")
+ if (!(await checkTicketCreationPerms(instance,originalOrigin,guild,user,option))) return cancel()
+
//get answers
const answers: {id:string,name:string,type:"short"|"paragraph",value:string|null}[] = []
option.get("opendiscord:questions").value.forEach((id) => {
@@ -227,18 +213,17 @@ export const registerModalResponders = async () => {
})
}
})
+
+ await instance.defer((generalConfig.data.ticketSystem.replyOnTicketCreation) ? "reply" : "update",true)
- //check ticket permissions
- if (!(await checkTicketCreationPerms(instance,originalSource,guild,user,option))) return cancel()
-
- //create ticket
- const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalSource,{guild,user,answers,option})
+ //CREATE TICKET
+ const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalOrigin,{guild,user,answers,option})
if (!res.channel || !res.ticket){
//error
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{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()
}
- if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(originalSource,{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}))
})
])
}
\ No newline at end of file
diff --git a/src/commands/topic.ts b/src/commands/topic.ts
index 79992c2..b2b15ad 100644
--- a/src/commands/topic.ts
+++ b/src/commands/topic.ts
@@ -1,44 +1,29 @@
///////////////////////////////////////
//TOPIC COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//TOPIC COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:topic",generalConfig.data.prefix,"topic"))
opendiscord.responders.commands.get("opendiscord:topic").workers.add([
- new api.ODWorker("opendiscord:topic",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:topic",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.topic,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/Server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"topic")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
@@ -48,16 +33,16 @@ export const registerCommandResponders = async () => {
const topic = instance.options.getString("topic",true)
//start changing ticket topic
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:update-ticket-topic").run(source,{guild,channel,user,ticket,newTopic:topic,sendMessage:false})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:topic-set").build(source,{guild,channel,user,ticket,topic}))
+ await opendiscord.actions.get("opendiscord:update-ticket-topic").run(origin,{guild,channel,user,ticket,newTopic:topic,sendMessage:false})
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:topic-set").build(origin,{guild,channel,user,ticket,topic}))
}
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'topic set' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/transfer.ts b/src/commands/transfer.ts
index 5aa2298..7857ef8 100644
--- a/src/commands/transfer.ts
+++ b/src/commands/transfer.ts
@@ -1,60 +1,47 @@
///////////////////////////////////////
//TRANSFER COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//TRANSFER COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:transfer",generalConfig.data.prefix,"transfer"))
opendiscord.responders.commands.get("opendiscord:transfer").workers.add([
- new api.ODWorker("opendiscord:transfer",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:transfer",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.transfer,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/Server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"transfer")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+ //fetch data
const oldCreator = await opendiscord.tickets.getTicketUser(ticket,"creator") ?? opendiscord.client.client.user
const newCreator = instance.options.getUser("user",true)
const reason = instance.options.getString("reason",false)
//start transferring ticket ownership
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:transfer-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,newCreator})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:transfer-message").build(source,{guild,channel,user,ticket,oldCreator,newCreator,reason}))
+ await opendiscord.actions.get("opendiscord:transfer-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,newCreator})
+ await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:transfer-message").build(origin,{guild,channel,user,ticket,oldCreator,newCreator,reason}))
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'transfer' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
diff --git a/src/commands/unclaim.ts b/src/commands/unclaim.ts
index 73cb608..6250061 100644
--- a/src/commands/unclaim.ts
+++ b/src/commands/unclaim.ts
@@ -1,116 +1,233 @@
///////////////////////////////////////
//UNCLAIM COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//UNCLAIM COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:unclaim",generalConfig.data.prefix,"unclaim"))
opendiscord.responders.commands.get("opendiscord:unclaim").workers.add([
- new api.ODWorker("opendiscord:unclaim",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:unclaim",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.unclaim,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/Server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when not claimed
- if (!ticket.get("opendiscord:claimed").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"}))
- return cancel()
- }
-
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const reason = instance.options.getString("reason",false)
-
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unclaim")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketClaimed = await openticketUtils.replyTicketMustBeClaimed(instance,origin,ticket)
+ if (!isTicketClaimed) return cancel()
+
//start unclaiming ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:unclaim-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(source,{guild,channel,user,ticket,reason}))
+ const reason = instance.options.getString("reason",false)
+ await opendiscord.actions.get("opendiscord:unclaim-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
+
+ //send message & set state
+ const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"unclaim-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'unclaim' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//UNCLAIM TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:unclaim-ticket",/^od:unclaim-ticket/))
opendiscord.responders.buttons.get("opendiscord:unclaim-ticket").workers.add(
- new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => {
- const originalSource = instance.interaction.customId.split("_")[1] as Exclude
+ new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,user,message} = instance
- if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").activate(instance)
- else if (originalSource == "claim-message") await opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").activate(instance)
- else await instance.defer("update",false)
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unclaim")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unclaim")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketClaimed = await openticketUtils.replyTicketMustBeClaimed(instance,origin,ticket)
+ if (!isTicketClaimed) return cancel()
+
+ //fetch state details
+ const verifybar = opendiscord.verifybars.get("opendiscord:unclaim-ticket")
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //send verifybar
+ if (generalConfig.data.ticketSystem.disableVerifyBars){
+ //verifybar disabled, directly run response
+ await verifybar.activate(instance,"accept")
+
+ }else if (originalMsgType == "ticket-message"){
+ //ticket message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:unclaim-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "claim-message"){
+ //claim message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:unclaim-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:claim-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
})
)
}
-export const registerModalResponders = async () => {
+export async function registerVerifyBars(){
+ //UNCLAIM TICKET
+ opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unclaim-ticket"))
+ opendiscord.verifybars.get("opendiscord:unclaim-ticket").workers.add([
+ new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,origin,cancel) => {
+ const {user,member,channel,guild,message} = instance
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unclaim")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unclaim")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketClaimed = await openticketUtils.replyTicketMustBeClaimed(instance,origin,ticket)
+ if (!isTicketClaimed) return cancel()
+
+ //fetch state details
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //start unclaiming ticket
+ if (params.selectedButtonId == "cancel"){
+ //CANCEL
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "claim-message"){
+ //claim message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
+ }else if (params.selectedButtonId == "accept"){
+ //UNCLAIM TICKET
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "claim-message"){
+ //converted to unclaim message
+ await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"unclaim-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:null
+ },sentMsg.ephemeral)
+ }
+ }else if (params.selectedButtonId == "accept-with-reason"){
+ //UNCLAIM WITH REASON (MODAL)
+ instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unclaim-ticket-reason").build("other",{guild,channel,user,ticket,message}))
+ }
+ })
+ ])
+}
+
+export async function registerModalResponders(){
//UNCLAIM WITH REASON MODAL RESPONDER
- opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unclaim-ticket-reason",/^od:unclaim-ticket-reason_/))
+ opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unclaim-ticket-reason",/^od:unclaim-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:unclaim-ticket-reason").workers.add([
- new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!channel) return
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
+ new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,origin,cancel) => {
+ const {guild,user} = instance
+
+ const match = /^od:unclaim-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
+ if (!match) return cancel()
+ const channel = await opendiscord.client.fetchTextChannel(match[1])
+ const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unclaim")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
- const originalSource = instance.interaction.customId.split("_")[2] as Exclude
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unclaim")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketClaimed = await openticketUtils.replyTicketMustBeClaimed(instance,origin,ticket)
+ if (!isTicketClaimed) return cancel()
+
+ //fetch state details
const reason = instance.values.getTextField("reason",true)
+ const originalMsgOrigin = state.data.messageOrigin
+ const originalMsgType = state.data.messageType
- //unclaim with reason
- if (originalSource == "ticket-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
+ //start claiming ticket
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }else if (originalSource == "claim-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason}))
- }else{
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
+
+ }else if (originalMsgType == "claim-message"){
+ //converted to unclaim message
+ await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"unclaim-message",
+ messageOrigin:originalMsgOrigin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
}
})
])
diff --git a/src/commands/unpin.ts b/src/commands/unpin.ts
index 30a9579..a49d772 100644
--- a/src/commands/unpin.ts
+++ b/src/commands/unpin.ts
@@ -1,116 +1,233 @@
///////////////////////////////////////
//UNPIN COMMAND
///////////////////////////////////////
-import {opendiscord, api, utilities} from "../index"
+import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
+const lang = opendiscord.languages
+const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
-export const registerCommandResponders = async () => {
+export async function registerCommandResponders(){
//UNPIN COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:unpin",generalConfig.data.prefix,"unpin"))
opendiscord.responders.commands.get("opendiscord:unpin").workers.add([
- new api.ODWorker("opendiscord:unpin",0,async (instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:unpin",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
-
- //check permissions
- const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.unpin,"support",user,member,channel,guild)
- 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}))
- else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions:["support"]}))
- return cancel()
- }
-
- //check is in guild/Server
- if (!guild){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
- return cancel()
- }
-
- //check if ticket exists
- const ticket = opendiscord.tickets.get(channel.id)
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return cancel()
- }
-
- //return when not pinned yet
- if (!ticket.get("opendiscord:pinned").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"}))
- return cancel()
- }
- //return when busy
- if (ticket.get("opendiscord:busy").value){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
- return cancel()
- }
-
- const reason = instance.options.getString("reason",false)
-
- //start unpinning ticket
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unpin")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketPinned = await openticketUtils.replyTicketMustBePinned(instance,origin,ticket)
+ if (!isTicketPinned) return cancel()
+
+ //start unpining ticket
await instance.defer(false)
- await opendiscord.actions.get("opendiscord:unpin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(source,{guild,channel,user,ticket,reason}))
+ const reason = instance.options.getString("reason",false)
+ await opendiscord.actions.get("opendiscord:unpin-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
+
+ //send message & set state
+ const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(origin,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"unpin-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
}),
- new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
+ new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'unpin' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
- {key:"method",value:source}
+ {key:"method",value:origin}
])
})
])
}
-export const registerButtonResponders = async () => {
+export async function registerButtonResponders(){
//UNPIN TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:unpin-ticket",/^od:unpin-ticket/))
opendiscord.responders.buttons.get("opendiscord:unpin-ticket").workers.add(
- new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => {
- const originalSource = instance.interaction.customId.split("_")[1] as Exclude
+ new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,origin,cancel) => {
+ const {guild,channel,user,message} = instance
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unpin")
+ if (!hasPerms) return cancel()
- if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").activate(instance)
- else if (originalSource == "pin-message") await opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").activate(instance)
- else await instance.defer("update",false)
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unpin")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketPinned = await openticketUtils.replyTicketMustBePinned(instance,origin,ticket)
+ if (!isTicketPinned) return cancel()
+
+ //fetch state details
+ const verifybar = opendiscord.verifybars.get("opendiscord:unpin-ticket")
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //send verifybar
+ if (generalConfig.data.ticketSystem.disableVerifyBars){
+ //verifybar disabled, directly run response
+ await verifybar.activate(instance,"accept")
+
+ }else if (originalMsgType == "ticket-message"){
+ //ticket message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:unpin-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "pin-message"){
+ //pin message verifybar
+ const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:unpin-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:pin-message"),originalMsgType,{guild,channel,user,verifybar})
+ await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
})
)
}
-export const registerModalResponders = async () => {
+export async function registerVerifyBars(){
+ //UNPIN TICKET
+ opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unpin-ticket"))
+ opendiscord.verifybars.get("opendiscord:unpin-ticket").workers.add([
+ new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,origin,cancel) => {
+ const {user,member,channel,guild,message} = instance
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unpin")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || channel.isDMBased()) return cancel()
+
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unpin")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketPinned = await openticketUtils.replyTicketMustBePinned(instance,origin,ticket)
+ if (!isTicketPinned) return cancel()
+
+ //fetch state details
+ const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
+ const originalReason = state.data.messageReason ?? null
+ const originalMsgType = state.data.messageType
+
+ //start unpinning ticket
+ if (params.selectedButtonId == "cancel"){
+ //CANCEL
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "pin-message"){
+ //pin message
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
+ }
+ }else if (params.selectedButtonId == "accept"){
+ //UNPIN TICKET
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
+ await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
+ }else if (originalMsgType == "pin-message"){
+ //converted to unpin message
+ await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"unpin-message",
+ messageOrigin:origin,
+ messageAuthor:user.id,
+ messageReason:null
+ },sentMsg.ephemeral)
+ }
+ }else if (params.selectedButtonId == "accept-with-reason"){
+ //UNPIN WITH REASON (MODAL)
+ instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unpin-ticket-reason").build("other",{guild,channel,user,ticket,message}))
+ }
+ })
+ ])
+}
+
+export async function registerModalResponders(){
//UNPIN WITH REASON MODAL RESPONDER
- opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unpin-ticket-reason",/^od:unpin-ticket-reason_/))
+ opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unpin-ticket-reason",/^od:unpin-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:unpin-ticket-reason").workers.add([
- new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,source,cancel) => {
- const {guild,channel,user} = instance
- if (!channel) return
- if (!guild){
- //error
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
- return cancel()
- }
- const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
- if (!ticket || channel.isDMBased()){
- instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
- return
- }
+ new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,origin,cancel) => {
+ const {guild,user} = instance
+
+ const match = /^od:unpin-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
+ if (!match) return cancel()
+ const channel = await opendiscord.client.fetchTextChannel(match[1])
+ const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
+
+ //responder checks
+ const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unpin")
+ if (!hasPerms) return cancel()
+
+ const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
+ if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
- const originalSource = instance.interaction.customId.split("_")[2] as Exclude
+ const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unpin")
+ if (!state) return cancel()
+
+ const ticket = await openticketUtils.replyIsTicket(instance,origin)
+ if (!ticket) return cancel()
+
+ const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
+ if (!isAvailable) return cancel()
+
+ const isTicketPinned = await openticketUtils.replyTicketMustBePinned(instance,origin,ticket)
+ if (!isTicketPinned) return cancel()
+
+ //fetch state details
const reason = instance.values.getTextField("reason",true)
+ const originalMsgOrigin = state.data.messageOrigin
+ const originalMsgType = state.data.messageType
- //unpin with reason
- if (originalSource == "ticket-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
+ //start pinning ticket
+ await instance.defer("update",false)
+
+ if (originalMsgType == "ticket-message"){
+ //ticket message
+ await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
- }else if (originalSource == "pin-message"){
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
- await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason}))
- }else{
- await instance.defer("update",false)
- await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
+
+ }else if (originalMsgType == "pin-message"){
+ //converted to unpin message
+ await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
+ const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
+ if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
+ messageType:"unpin-message",
+ messageOrigin:originalMsgOrigin,
+ messageAuthor:user.id,
+ messageReason:reason
+ },sentMsg.ephemeral)
}
})
])
diff --git a/src/components/_INFO.md b/src/components/_INFO.md
new file mode 100644
index 0000000..ccf360e
--- /dev/null
+++ b/src/components/_INFO.md
@@ -0,0 +1,13 @@
+Open Discord Components:
+------------------------
+
+The "Components" system will be the new way of creating message and modal templates in Open Discord with support for Discord components v2.
+
+Messages, embeds, modals, buttons, etc are currently constructed using the "Builders" system located in `./src/builders/...`.
+
+This will be replaced with the new component factories in `./src/components/...`.
+
+### Timing
+Messages, modals & components will slowly be migrated to the new system during upcoming updates. The full migration will happen after `Open Ticket v4.3` and the HTML Transcripts v3 are ready for it.
+
+For more information, contact [DJj123dj](https://github.com/DJj123dj) on Discord, Github or via email
\ No newline at end of file
diff --git a/src/components/verifybarModifiers.ts b/src/components/verifybarModifiers.ts
new file mode 100644
index 0000000..60d35ed
--- /dev/null
+++ b/src/components/verifybarModifiers.ts
@@ -0,0 +1,138 @@
+///////////////////////////////////////
+//VERIFYBAR MESSAGE MODIFIERS
+///////////////////////////////////////
+import {opendiscord, api, utilities} from "../index.js"
+import * as discord from "discord.js"
+
+const modifiers = opendiscord.components.modifiers
+const lang = opendiscord.languages
+const generalConfig = opendiscord.configs.get("opendiscord:general")
+
+export async function addVerifyButton(instance:api.ODMessageInstance|api.ODComponentFactoryInstance,params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:api.ODVerifyBar},defaultButtonType:"โ
"|"โ",useDefaultLabels:boolean,verifyButtonId:string,customLabel?:string,customColor?:api.ODValidButtonColor,customEmoji?:string){
+ const {guild,channel,user,verifybar} = params
+ if (instance instanceof api.ODMessageInstance){
+ //message builders
+ instance.addComponent(await opendiscord.builders.buttons.getSafe("opendiscord:verifybar-button").build("verifybar",{
+ guild,channel,user,verifybar,
+ defaultButtonType,useDefaultLabels,customColor,customEmoji,customLabel,
+ verifyButtonId
+ }))
+ }else{
+ //message components
+ throw new api.ODSystemError("registerAllVerifyBarModifiers addVerifyButton() => verifybar doesn't support ODComponents v2 yet!")
+ //const message = instance.getComponent()
+ //if (!message) return
+ //const actionRow: api.ODActionRowComponent|null = message.getComponentsOfType("action-row")[0]
+ //if (actionRow) actionRow.addComponent(new api.ODButtonComponent("opendiscord:verifybar-button",{
+ // //TODO
+ //}),"end")
+ }
+}
+
+export async function registerAllVerifyBarModifiers(){
+ //CLOSE TICKET VERIFYBAR
+ modifiers.add(new api.ODMessageComponentModifier("opendiscord:close-ticket-verifybar"))
+ modifiers.get("opendiscord:close-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:close-ticket-verifybar",100,async (instance,params,origin,cancel) => {
+ if (instance instanceof api.ODMessageInstance){
+ instance.data.components = [] //clear actionrow
+ }else{
+ throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
+ }
+
+ //cancel, accept or close with reason
+ await addVerifyButton(instance,params,"โ",true,api.ODVerifyButtonId.Cancel)
+ await addVerifyButton(instance,params,"โ
",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.close"))
+ if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"โ
",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","โ๏ธ")
+ }))
+
+ //REOPEN TICKET VERIFYBAR
+ modifiers.add(new api.ODMessageComponentModifier("opendiscord:reopen-ticket-verifybar"))
+ modifiers.get("opendiscord:reopen-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:reopen-ticket-verifybar",100,async (instance,params,origin,cancel) => {
+ if (instance instanceof api.ODMessageInstance){
+ instance.data.components = [] //clear actionrow
+ }else{
+ throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
+ }
+
+ //cancel, accept or reopen with reason
+ await addVerifyButton(instance,params,"โ",true,api.ODVerifyButtonId.Cancel)
+ await addVerifyButton(instance,params,"โ
",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.reopen"))
+ if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"โ
",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","โ๏ธ")
+ }))
+
+ //DELETE TICKET VERIFYBAR
+ modifiers.add(new api.ODMessageComponentModifier("opendiscord:delete-ticket-verifybar"))
+ modifiers.get("opendiscord:delete-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:delete-ticket-verifybar",100,async (instance,params,origin,cancel) => {
+ if (instance instanceof api.ODMessageInstance){
+ instance.data.components = [] //clear actionrow
+ }else{
+ throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
+ }
+
+ //cancel, accept or delete with reason or without transcript
+ await addVerifyButton(instance,params,"โ",true,api.ODVerifyButtonId.Cancel)
+ await addVerifyButton(instance,params,"โ
",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.delete"))
+ if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"โ
",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","โ๏ธ")
+ if (generalConfig.data.ticketSystem.enableDeleteWithoutTranscript) await addVerifyButton(instance,params,"โ
",false,api.ODVerifyButtonId.AcceptWithoutTranscript,lang.getTranslation("actions.buttons.withoutTranscript"),"red","๐")
+ }))
+
+ //CLAIM TICKET VERIFYBAR
+ modifiers.add(new api.ODMessageComponentModifier("opendiscord:claim-ticket-verifybar"))
+ modifiers.get("opendiscord:claim-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:claim-ticket-verifybar",100,async (instance,params,origin,cancel) => {
+ if (instance instanceof api.ODMessageInstance){
+ instance.data.components = [] //clear actionrow
+ }else{
+ throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
+ }
+
+ //cancel, accept or claim with reason
+ await addVerifyButton(instance,params,"โ",true,api.ODVerifyButtonId.Cancel)
+ await addVerifyButton(instance,params,"โ
",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.claim"))
+ if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"โ
",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","โ๏ธ")
+ }))
+
+ //UNCLAIM TICKET VERIFYBAR
+ modifiers.add(new api.ODMessageComponentModifier("opendiscord:unclaim-ticket-verifybar"))
+ modifiers.get("opendiscord:unclaim-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:unclaim-ticket-verifybar",100,async (instance,params,origin,cancel) => {
+ if (instance instanceof api.ODMessageInstance){
+ instance.data.components = [] //clear actionrow
+ }else{
+ throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
+ }
+
+ //cancel, accept or unclaim with reason
+ await addVerifyButton(instance,params,"โ",true,api.ODVerifyButtonId.Cancel)
+ await addVerifyButton(instance,params,"โ
",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.unclaim"))
+ if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"โ
",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","โ๏ธ")
+ }))
+
+ //PIN TICKET VERIFYBAR
+ modifiers.add(new api.ODMessageComponentModifier("opendiscord:pin-ticket-verifybar"))
+ modifiers.get("opendiscord:pin-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:pin-ticket-verifybar",100,async (instance,params,origin,cancel) => {
+ if (instance instanceof api.ODMessageInstance){
+ instance.data.components = [] //clear actionrow
+ }else{
+ throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
+ }
+
+ //cancel, accept or pin with reason
+ await addVerifyButton(instance,params,"โ",true,api.ODVerifyButtonId.Cancel)
+ await addVerifyButton(instance,params,"โ
",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.pin"))
+ if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"โ
",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","โ๏ธ")
+ }))
+
+ //UNPIN TICKET VERIFYBAR
+ modifiers.add(new api.ODMessageComponentModifier("opendiscord:unpin-ticket-verifybar"))
+ modifiers.get("opendiscord:unpin-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:unpin-ticket-verifybar",100,async (instance,params,origin,cancel) => {
+ if (instance instanceof api.ODMessageInstance){
+ instance.data.components = [] //clear actionrow
+ }else{
+ throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
+ }
+
+ //cancel, accept or unpin with reason
+ await addVerifyButton(instance,params,"โ",true,api.ODVerifyButtonId.Cancel)
+ await addVerifyButton(instance,params,"โ
",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.unpin"))
+ if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"โ
",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","โ๏ธ")
+ }))
+}
\ No newline at end of file
diff --git a/src/core/api.ts b/src/core/api.ts
new file mode 100644
index 0000000..d9df578
--- /dev/null
+++ b/src/core/api.ts
@@ -0,0 +1,43 @@
+//EXPORT FRAMEWORK
+export * from "@open-discord-bots/framework/api"
+
+//EXPORT OPEN TICKET MAPPINGS
+export * from "./mappings/action.js"
+export * from "./mappings/base.js"
+export * from "./mappings/builder.js"
+export * from "./mappings/checker.js"
+export * from "./mappings/client.js"
+export * from "./mappings/code.js"
+export * from "./mappings/component.js"
+export * from "./mappings/config.js"
+export * from "./mappings/console.js"
+export * from "./mappings/cooldown.js"
+export * from "./mappings/database.js"
+export * from "./mappings/event.js"
+export * from "./mappings/flag.js"
+export * from "./mappings/fuse.js"
+export * from "./mappings/helpmenu.js"
+export * from "./mappings/language.js"
+export * from "./mappings/permission.js"
+export * from "./mappings/plugin.js"
+export * from "./mappings/post.js"
+export * from "./mappings/progressbar.js"
+export * from "./mappings/responder.js"
+export * from "./mappings/session.js"
+export * from "./mappings/startscreen.js"
+export * from "./mappings/state.js"
+export * from "./mappings/statistic.js"
+export * from "./mappings/verifybar.js"
+
+//EXPORT OPENTICKET MODULES
+export * from "./api/blacklist.js"
+export * from "./api/option.js"
+export * from "./api/panel.js"
+export * from "./api/priority.js"
+export * from "./api/question.js"
+export * from "./api/role.js"
+export * from "./api/ticket.js"
+export * from "./api/transcript.js"
+
+//EXPORT MAIN MODULE
+export { ODOpenTicketMain } from "./main.js"
\ No newline at end of file
diff --git a/src/core/api/api.ts b/src/core/api/api.ts
deleted file mode 100644
index 7286d8f..0000000
--- a/src/core/api/api.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-//MAIN MODULE
-export * from "./main"
-
-//BASE MODULES
-export * from "./modules/base"
-export * from "./modules/event"
-export * from "./modules/config"
-export * from "./modules/database"
-export * from "./modules/language"
-export * from "./modules/flag"
-export * from "./modules/console"
-export * from "./modules/defaults"
-export * from "./modules/plugin"
-export * from "./modules/checker"
-export * from "./modules/client"
-export * from "./modules/worker"
-export * from "./modules/builder"
-export * from "./modules/responder"
-export * from "./modules/action"
-export * from "./modules/permission"
-export * from "./modules/helpmenu"
-export * from "./modules/session"
-export * from "./modules/stat"
-export * from "./modules/code"
-export * from "./modules/cooldown"
-export * from "./modules/post"
-export * from "./modules/verifybar"
-export * from "./modules/progressbar"
-export * from "./modules/startscreen"
-
-//OPENTICKET DEFAULT MODULES
-export * from "./defaults/base"
-export * from "./defaults/event"
-export * from "./defaults/config"
-export * from "./defaults/database"
-export * from "./defaults/plugin"
-export * from "./defaults/checker"
-export * from "./defaults/client"
-export * from "./defaults/language"
-export * from "./defaults/builder"
-export * from "./defaults/responder"
-export * from "./defaults/action"
-export * from "./defaults/flag"
-export * from "./defaults/permission"
-export * from "./defaults/helpmenu"
-export * from "./defaults/session"
-export * from "./defaults/stat"
-export * from "./defaults/worker"
-export * from "./defaults/code"
-export * from "./defaults/cooldown"
-export * from "./defaults/post"
-export * from "./defaults/progressbar"
-export * from "./defaults/startscreen"
-export * from "./defaults/console"
-
-//OPENTICKET MODULES
-export * from "./openticket/question"
-export * from "./openticket/option"
-export * from "./openticket/panel"
-export * from "./openticket/ticket"
-export * from "./openticket/blacklist"
-export * from "./openticket/transcript"
-export * from "./openticket/role"
-export * from "./openticket/priority"
\ No newline at end of file
diff --git a/src/core/api/openticket/blacklist.ts b/src/core/api/blacklist.ts
similarity index 69%
rename from src/core/api/openticket/blacklist.ts
rename to src/core/api/blacklist.ts
index d7dedcd..391f526 100644
--- a/src/core/api/openticket/blacklist.ts
+++ b/src/core/api/blacklist.ts
@@ -1,8 +1,7 @@
///////////////////////////////////////
//OPENTICKET BLACKLIST MODULE
///////////////////////////////////////
-import { ODManager, ODManagerData, ODValidId } from "../modules/base"
-import { ODDebugger } from "../modules/console"
+import * as api from "@open-discord-bots/framework/api"
/**## ODBlacklist `class`
* This is an Open Ticket blacklisted user.
@@ -11,22 +10,22 @@ import { ODDebugger } from "../modules/console"
*
* Create this class & add it to the `ODBlacklistManager` to blacklist someone!
*/
-export class ODBlacklist extends ODManagerData {
+export class ODBlacklist extends api.ODManagerData {
/**The reason why this user got blacklisted. (optional) */
- #reason: string|null
+ private rawReason: string|null
- constructor(id:ODValidId,reason:string|null){
+ constructor(id:api.ODValidId,reason:string|null){
super(id)
- this.#reason = reason
+ this.rawReason = reason
}
/**The reason why this user got blacklisted. (optional) */
set reason(reason:string|null) {
- this.#reason = reason
+ this.rawReason = reason
this._change()
}
get reason(){
- return this.#reason
+ return this.rawReason
}
}
@@ -37,8 +36,8 @@ export class ODBlacklist extends ODManagerData {
*
* All `ODBlacklist`'s added, removed & edited in this list will be synced automatically with the database.
*/
-export class ODBlacklistManager extends ODManager {
- constructor(debug:ODDebugger){
+export class ODBlacklistManager extends api.ODManager {
+ constructor(debug:api.ODDebugger){
super(debug,"blacklist")
}
}
\ No newline at end of file
diff --git a/src/core/api/defaults/base.ts b/src/core/api/defaults/base.ts
deleted file mode 100644
index 2cfa279..0000000
--- a/src/core/api/defaults/base.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-///////////////////////////////////////
-//BASE MODULE
-///////////////////////////////////////
-import { ODVersion, ODVersionManager, ODValidId } from "../modules/base"
-
-/**## ODVersionManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODVersionManager` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODVersionManagerIds_Default {
- "opendiscord:version":ODVersion,
- "opendiscord:last-version":ODVersion,
- "opendiscord:api":ODVersion,
- "opendiscord:transcripts":ODVersion,
- "opendiscord:livestatus":ODVersion
-}
-
-/**## ODFlagManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODFlagManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.flags`!
- */
-export class ODVersionManager_Default extends ODVersionManager {
- get(id:VersionId): ODVersionManagerIds_Default[VersionId]
- get(id:ODValidId): ODVersion|null
-
- get(id:ODValidId): ODVersion|null {
- return super.get(id)
- }
-
- remove(id:VersionId): ODVersionManagerIds_Default[VersionId]
- remove(id:ODValidId): ODVersion|null
-
- remove(id:ODValidId): ODVersion|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODVersionManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/builder.ts b/src/core/api/defaults/builder.ts
deleted file mode 100644
index 96c652b..0000000
--- a/src/core/api/defaults/builder.ts
+++ /dev/null
@@ -1,549 +0,0 @@
-///////////////////////////////////////
-//DEFAULT BUILDER MODULE
-///////////////////////////////////////
-import { ODValidButtonColor, ODValidId } from "../modules/base"
-import { ODBuilderManager, ODButton, ODButtonInstance, ODButtonManager, ODDropdown, ODDropdownInstance, ODDropdownManager, ODEmbed, ODEmbedInstance, ODEmbedManager, ODFile, ODFileInstance, ODFileManager, ODMessage, ODMessageInstance, ODMessageManager, ODModal, ODModalInstance, ODModalManager } from "../modules/builder"
-import { ODWorkerManager_Default } from "./worker"
-import { ODTicket, ODTicketClearFilter } from "../openticket/ticket"
-import { ODPermissionEmbedType } from "../defaults/permission"
-import { ODTextCommandErrorInvalidOption, ODTextCommandErrorMissingOption, ODTextCommandErrorUnknownCommand } from "../modules/client"
-import { ODPanel } from "../openticket/panel"
-import { ODRoleOption, ODTicketOption, ODWebsiteOption } from "../openticket/option"
-import { ODVerifyBar } from "../modules/verifybar"
-import * as discord from "discord.js"
-import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript"
-import { ODRole, ODRoleUpdateResult } from "../openticket/role"
-import { ODPriorityLevel } from "../openticket/priority"
-
-/**## ODBuilderManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODBuilderManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.builders`!
- */
-export class ODBuilderManager_Default extends ODBuilderManager {
- declare buttons: ODButtonManager_Default
- declare dropdowns: ODDropdownManager_Default
- declare files: ODFileManager_Default
- declare embeds: ODEmbedManager_Default
- declare messages: ODMessageManager_Default
- declare modals: ODModalManager_Default
-}
-
-/**## ODButtonManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODButtonManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODButtonManagerIds_Default {
- "opendiscord:verifybar-success":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"opendiscord:verifybar-success"},
- "opendiscord:verifybar-failure":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"opendiscord:verifybar-failure"},
-
- "opendiscord:error-ticket-deprecated-transcript":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{},workers:"opendiscord:error-ticket-deprecated-transcript"},
-
- "opendiscord:help-menu-previous":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-previous"},
- "opendiscord:help-menu-next":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-next"},
- "opendiscord:help-menu-page":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-page"}
- "opendiscord:help-menu-switch":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-switch"},
-
- "opendiscord:ticket-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODTicketOption},workers:"opendiscord:ticket-option"},
- "opendiscord:website-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODWebsiteOption},workers:"opendiscord:website-option"},
- "opendiscord:role-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODRoleOption},workers:"opendiscord:role-option"}
-
- "opendiscord:visit-ticket":{source:"ticket-created"|"dm"|"logs"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:visit-ticket"},
-
- "opendiscord:close-ticket":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:close-ticket"},
- "opendiscord:delete-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:delete-ticket"},
- "opendiscord:reopen-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:reopen-ticket"},
- "opendiscord:claim-ticket":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:claim-ticket"},
- "opendiscord:unclaim-ticket":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unclaim-ticket"},
- "opendiscord:pin-ticket":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:pin-ticket"},
- "opendiscord:unpin-ticket":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unpin-ticket"},
-
- "opendiscord:transcript-html-visit":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-visit"},
- "opendiscord:transcript-error-retry":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"opendiscord:transcript-error-retry"},
- "opendiscord:transcript-error-continue":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"opendiscord:transcript-error-continue"},
-
- "opendiscord:clear-continue":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-continue"},
-}
-
-/**## ODButtonManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODButtonManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.builders.buttons`!
- */
-export class ODButtonManager_Default extends ODButtonManager {
- get(id:ButtonId): ODButton_Default
- get(id:ODValidId): ODButton|null
-
- get(id:ODValidId): ODButton|null {
- return super.get(id)
- }
-
- remove(id:ButtonId): ODButton_Default
- remove(id:ODValidId): ODButton|null
-
- remove(id:ODValidId): ODButton|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODButtonManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- getSafe(id:ButtonId): ODButton_Default
- getSafe(id:ODValidId): ODButton
-
- getSafe(id:ODValidId): ODButton {
- return super.getSafe(id)
- }
-}
-
-/**## ODButton_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODButton class.
- * It doesn't add any extra features!
- *
- * This default class is made for the default `ODButton`'s!
- */
-export class ODButton_Default extends ODButton {
- declare workers: ODWorkerManager_Default
-}
-
-/**## ODDropdownManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODDropdownManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODDropdownManagerIds_Default {
- "opendiscord:panel-dropdown-tickets":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,options:ODTicketOption[]},workers:"opendiscord:panel-dropdown-tickets"}
-}
-
-/**## ODDropdownManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODDropdownManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.builders.dropdowns`!
- */
-export class ODDropdownManager_Default extends ODDropdownManager {
- get(id:DropdownId): ODDropdown_Default
- get(id:ODValidId): ODDropdown|null
-
- get(id:ODValidId): ODDropdown|null {
- return super.get(id)
- }
-
- remove(id:DropdownId): ODDropdown_Default
- remove(id:ODValidId): ODDropdown|null
-
- remove(id:ODValidId): ODDropdown|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODDropdownManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- getSafe(id:DropdownId): ODDropdown_Default
- getSafe(id:ODValidId): ODDropdown
-
- getSafe(id:ODValidId): ODDropdown {
- return super.getSafe(id)
- }
-}
-
-/**## ODDropdown_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODDropdown class.
- * It doesn't add any extra features!
- *
- * This default class is made for the default `ODDropdown`'s!
- */
-export class ODDropdown_Default extends ODDropdown {
- declare workers: ODWorkerManager_Default
-}
-
-/**## ODFileManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODFileManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODFileManagerIds_Default {
- "opendiscord:text-transcript":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,result:ODTranscriptCompilerCompileResult},workers:"opendiscord:text-transcript"}
-}
-
-/**## ODFileManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODFileManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.builders.files`!
- */
-export class ODFileManager_Default extends ODFileManager {
- get(id:FileId): ODFile_Default
- get(id:ODValidId): ODFile|null
-
- get(id:ODValidId): ODFile|null {
- return super.get(id)
- }
-
- remove(id:FileId): ODFile_Default
- remove(id:ODValidId): ODFile|null
-
- remove(id:ODValidId): ODFile|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODFileManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- getSafe(id:FileId): ODFile_Default
- getSafe(id:ODValidId): ODFile
-
- getSafe(id:ODValidId): ODFile {
- return super.getSafe(id)
- }
-}
-
-/**## ODFile_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODFile class.
- * It doesn't add any extra features!
- *
- * This default class is made for the default `ODFile`'s!
- */
-export class ODFile_Default extends ODFile {
- declare workers: ODWorkerManager_Default
-}
-
-/**## ODEmbedManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODEmbedManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODEmbedManagerIds_Default {
- "opendiscord:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced",customTitle?:string},workers:"opendiscord:error"},
- "opendiscord:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"opendiscord:error-option-missing"},
- "opendiscord:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"opendiscord:error-option-invalid"},
- "opendiscord:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"opendiscord:error-unknown-command"},
- "opendiscord:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"opendiscord:error-no-permissions"},
- "opendiscord:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"opendiscord:error-no-permissions-cooldown"},
- "opendiscord:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-no-permissions-blacklisted"},
- "opendiscord:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"opendiscord:error-no-permissions-limits"},
- "opendiscord:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-responder-timeout"},
- "opendiscord:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-unknown"},
- "opendiscord:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-deprecated"},
- "opendiscord:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-option-unknown"},
- "opendiscord:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-panel-unknown"},
- "opendiscord:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-not-in-guild"},
- "opendiscord:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"ticket-priority"|"ticket-transfer"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"opendiscord:error-channel-rename"},
- "opendiscord:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-busy"},
-
- "opendiscord:help-menu":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu"},
-
- "opendiscord:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:stats-global"},
- "opendiscord:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"opendiscord:stats-ticket"},
- "opendiscord:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"opendiscord:stats-user"|"opendiscord:easter-egg"},
- "opendiscord:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"opendiscord:stats-reset"},
- "opendiscord:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"opendiscord:stats-ticket-unknown"},
-
- "opendiscord:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"opendiscord:panel"},
- "opendiscord:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created"},
- "opendiscord:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-dm"},
- "opendiscord:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-logs"},
- "opendiscord:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-message"},
- "opendiscord:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:close-message"},
- "opendiscord:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:reopen-message"},
- "opendiscord:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:delete-message"},
- "opendiscord:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:claim-message"},
- "opendiscord:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unclaim-message"},
- "opendiscord:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:pin-message"},
- "opendiscord:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unpin-message"},
- "opendiscord:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"opendiscord:rename-message"},
- "opendiscord:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"opendiscord:move-message"},
- "opendiscord:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:add-message"},
- "opendiscord:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:remove-message"},
- "opendiscord:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-dm"},
- "opendiscord:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-logs"},
-
- "opendiscord:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:blacklist-view"},
- "opendiscord:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"opendiscord:blacklist-get"},
- "opendiscord:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-add"},
- "opendiscord:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-remove"}
- "opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"},
- "opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"},
-
- "opendiscord:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string},null>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"opendiscord:transcript-text-ready"},
- "opendiscord:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-ready"},
- "opendiscord:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,remaining:number},workers:"opendiscord:transcript-html-progress"},
- "opendiscord:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"opendiscord:transcript-error"},
-
- "opendiscord:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role"},
- "opendiscord:reaction-role-dm":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role-dm"},
- "opendiscord:reaction-role-logs":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role-logs"},
-
- "opendiscord:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-verify-message"},
- "opendiscord:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-message"},
- "opendiscord:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-logs"},
-
- "opendiscord:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autoclose-message"},
- "opendiscord:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autodelete-message"},
- "opendiscord:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autoclose-enable"},
- "opendiscord:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autodelete-enable"},
- "opendiscord:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autoclose-disable"},
- "opendiscord:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autodelete-disable"},
-
- "opendiscord:topic-set":{source:"slash"|"text"|"ticket-action"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,topic:string},workers:"opendiscord:topic-set"},
- "opendiscord:priority-set":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriorityLevel,reason:string|null},workers:"opendiscord:priority-set"},
- "opendiscord:priority-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriorityLevel},workers:"opendiscord:priority-get"},
- "opendiscord:transfer-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,oldCreator:discord.User,newCreator:discord.User,reason:string|null},workers:"opendiscord:transfer-message"},
-}
-
-/**## ODEmbedManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODEmbedManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.builders.embeds`!
- */
-export class ODEmbedManager_Default extends ODEmbedManager {
- get(id:EmbedId): ODEmbed_Default
- get(id:ODValidId): ODEmbed|null
-
- get(id:ODValidId): ODEmbed|null {
- return super.get(id)
- }
-
- remove(id:EmbedId): ODEmbed_Default
- remove(id:ODValidId): ODEmbed|null
-
- remove(id:ODValidId): ODEmbed|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODEmbedManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- getSafe(id:EmbedId): ODEmbed_Default
- getSafe(id:ODValidId): ODEmbed
-
- getSafe(id:ODValidId): ODEmbed {
- return super.getSafe(id)
- }
-}
-
-/**## ODEmbed_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODEmbed class.
- * It doesn't add any extra features!
- *
- * This default class is made for the default `ODEmbed`'s!
- */
-export class ODEmbed_Default extends ODEmbed {
- declare workers: ODWorkerManager_Default
-}
-
-/**## ODMessageManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODMessageManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODMessageManagerIds_Default {
- "opendiscord:verifybar-ticket-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-ticket-message"},
- "opendiscord:verifybar-close-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-close-message"},
- "opendiscord:verifybar-reopen-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-reopen-message"},
- "opendiscord:verifybar-claim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-claim-message"},
- "opendiscord:verifybar-unclaim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-unclaim-message"},
- "opendiscord:verifybar-pin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-pin-message"},
- "opendiscord:verifybar-unpin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-unpin-message"}
- "opendiscord:verifybar-autoclose-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-autoclose-message"}
-
- "opendiscord:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced",customTitle?:string},workers:"opendiscord:error"},
- "opendiscord:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"opendiscord:error-option-missing"},
- "opendiscord:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"opendiscord:error-option-invalid"},
- "opendiscord:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"opendiscord:error-unknown-command"},
- "opendiscord:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"opendiscord:error-no-permissions"},
- "opendiscord:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"opendiscord:error-no-permissions-cooldown"},
- "opendiscord:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-no-permissions-blacklisted"},
- "opendiscord:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"opendiscord:error-no-permissions-limits"},
- "opendiscord:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-responder-timeout"},
- "opendiscord:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-unknown"},
- "opendiscord:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-deprecated"},
- "opendiscord:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-option-unknown"},
- "opendiscord:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-panel-unknown"},
- "opendiscord:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-not-in-guild"},
- "opendiscord:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"ticket-priority"|"ticket-transfer"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"opendiscord:error-channel-rename"},
- "opendiscord:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-busy"},
-
- "opendiscord:help-menu":{source:"slash"|"text"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu"},
-
- "opendiscord:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:stats-global"},
- "opendiscord:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"opendiscord:stats-ticket"},
- "opendiscord:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"opendiscord:stats-user"|"opendiscord:easter-egg"},
- "opendiscord:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"opendiscord:stats-reset"},
- "opendiscord:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"opendiscord:stats-ticket-unknown"},
-
- "opendiscord:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"opendiscord:panel-layout"|"opendiscord:panel-components"},
- "opendiscord:panel-ready":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"opendiscord:panel-ready"},
-
- "opendiscord:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created"},
- "opendiscord:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-dm"},
- "opendiscord:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-logs"},
- "opendiscord:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-message-layout"|"opendiscord:ticket-message-components"|"opendiscord:ticket-message-disable-components"},
- "opendiscord:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:close-message"},
- "opendiscord:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:reopen-message"},
- "opendiscord:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:delete-message"},
- "opendiscord:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:claim-message"},
- "opendiscord:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unclaim-message"},
- "opendiscord:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:pin-message"},
- "opendiscord:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unpin-message"},
- "opendiscord:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"opendiscord:rename-message"},
- "opendiscord:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"opendiscord:move-message"},
- "opendiscord:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:add-message"},
- "opendiscord:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:remove-message"},
- "opendiscord:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-dm"},
- "opendiscord:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-logs"},
-
- "opendiscord:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:blacklist-view"},
- "opendiscord:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"opendiscord:blacklist-get"},
- "opendiscord:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-add"},
- "opendiscord:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-remove"},
- "opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"},
- "opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"},
-
- "opendiscord:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string},null>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"opendiscord:transcript-text-ready"},
- "opendiscord:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-ready"},
- "opendiscord:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,remaining:number},workers:"opendiscord:transcript-html-progress"},
- "opendiscord:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"opendiscord:transcript-error"},
-
- "opendiscord:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role"},
- "opendiscord:reaction-role-dm":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role-dm"},
- "opendiscord:reaction-role-logs":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role-logs"},
-
- "opendiscord:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-verify-message"},
- "opendiscord:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-message"},
- "opendiscord:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-logs"},
-
- "opendiscord:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autoclose-message"},
- "opendiscord:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autodelete-message"},
- "opendiscord:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autoclose-enable"},
- "opendiscord:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autodelete-enable"},
- "opendiscord:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autoclose-disable"},
- "opendiscord:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autodelete-disable"},
-
- "opendiscord:topic-set":{source:"slash"|"text"|"ticket-action"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,topic:string},workers:"opendiscord:topic-set"},
- "opendiscord:priority-set":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriorityLevel,reason:string|null},workers:"opendiscord:priority-set"},
- "opendiscord:priority-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriorityLevel},workers:"opendiscord:priority-get"},
- "opendiscord:transfer-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,oldCreator:discord.User,newCreator:discord.User,reason:string|null},workers:"opendiscord:transfer-message"},
-}
-
-/**## ODMessageManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODMessageManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.builders.messages`!
- */
-export class ODMessageManager_Default extends ODMessageManager {
- get(id:MessageId): ODMessage_Default
- get(id:ODValidId): ODMessage|null
-
- get(id:ODValidId): ODMessage|null {
- return super.get(id)
- }
-
- remove(id:MessageId): ODMessage_Default
- remove(id:ODValidId): ODMessage|null
-
- remove(id:ODValidId): ODMessage|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODMessageManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- getSafe(id:MessageId): ODMessage_Default
- getSafe(id:ODValidId): ODMessage
-
- getSafe(id:ODValidId): ODMessage {
- return super.getSafe(id)
- }
-}
-
-/**## ODMessage_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODMessage class.
- * It doesn't add any extra features!
- *
- * This default class is made for the default `ODMessage`'s!
- */
-export class ODMessage_Default extends ODMessage {
- declare workers: ODWorkerManager_Default
-}
-
-/**## ODModalManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODModalManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODModalManagerIds_Default {
- "opendiscord:ticket-questions":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,option:ODTicketOption},workers:"opendiscord:ticket-questions"}
- "opendiscord:close-ticket-reason":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:close-ticket-reason"}
- "opendiscord:reopen-ticket-reason":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:reopen-ticket-reason"}
- "opendiscord:delete-ticket-reason":{source:"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:delete-ticket-reason"}
- "opendiscord:claim-ticket-reason":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:claim-ticket-reason"}
- "opendiscord:unclaim-ticket-reason":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unclaim-ticket-reason"}
- "opendiscord:pin-ticket-reason":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:pin-ticket-reason"}
- "opendiscord:unpin-ticket-reason":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unpin-ticket-reason"}
-}
-
-/**## ODModalManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODModalManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.builders.modals`!
- */
-export class ODModalManager_Default extends ODModalManager {
- get(id:ModalId): ODModal_Default
- get(id:ODValidId): ODModal|null
-
- get(id:ODValidId): ODModal|null {
- return super.get(id)
- }
-
- remove(id:ModalId): ODModal_Default
- remove(id:ODValidId): ODModal|null
-
- remove(id:ODValidId): ODModal|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODModalManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- getSafe(id:ModalId): ODModal_Default
- getSafe(id:ODValidId): ODModal
-
- getSafe(id:ODValidId): ODModal {
- return super.getSafe(id)
- }
-}
-
-/**## ODModal_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODModal class.
- * It doesn't add any extra features!
- *
- * This default class is made for the default `ODModal`'s!
- */
-export class ODModal_Default extends ODModal {
- declare workers: ODWorkerManager_Default
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/checker.ts b/src/core/api/defaults/checker.ts
deleted file mode 100644
index 9cc654c..0000000
--- a/src/core/api/defaults/checker.ts
+++ /dev/null
@@ -1,385 +0,0 @@
-///////////////////////////////////////
-//DEFAULT CONFIG CHECKER MODULE
-///////////////////////////////////////
-import { ODLanguageManager_Default } from "../api"
-import { ODValidId } from "../modules/base"
-import { ODCheckerManager, ODChecker, ODCheckerTranslationRegister, ODCheckerRenderer, ODCheckerFunctionManager, ODCheckerResult, ODCheckerFunction } from "../modules/checker"
-import ansis from "ansis"
-
-/**## ODCheckerManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODCheckerManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODCheckerManagerIds_Default {
- "opendiscord:general":ODChecker,
- "opendiscord:questions":ODChecker,
- "opendiscord:options":ODChecker,
- "opendiscord:panels":ODChecker,
- "opendiscord:transcripts":ODChecker
-}
-
-/**## ODCheckerManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODCheckerManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.checkers`!
- */
-export class ODCheckerManager_Default extends ODCheckerManager {
- declare translation: ODCheckerTranslationRegister_Default
- declare renderer: ODCheckerRenderer_Default
- declare functions: ODCheckerFunctionManager_Default
-
- get(id:CheckerId): ODCheckerManagerIds_Default[CheckerId]
- get(id:ODValidId): ODChecker|null
-
- get(id:ODValidId): ODChecker|null {
- return super.get(id)
- }
-
- remove(id:CheckerId): ODCheckerManagerIds_Default[CheckerId]
- remove(id:ODValidId): ODChecker|null
-
- remove(id:ODValidId): ODChecker|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODCheckerManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
-
-/**## ODCheckerRenderer_Default `default_class`
- * This is a special class that adds type definitions & features to the ODCheckerRenderer class.
- * It contains the code that renders the default config checker.
- *
- * This default class is made for the global variable `opendiscord.checkers.renderer`!
- */
-export class ODCheckerRenderer_Default extends ODCheckerRenderer {
- extraHeaderText: string[] = []
- extraFooterText: string[] = []
- extraTopText: string[] = []
- extraBottomText: string[] = []
-
- horizontalFiller: string = "="
- verticalFiller: string = "|"
- descriptionSeparator: string = " => "
- headerSeparator: string = " => "
- footerTipPrefix: string = "=> "
-
- disableHeader: boolean = false
- disableFooter: boolean = false
-
- getComponents(compact:boolean, renderEmpty:boolean, translation:ODCheckerTranslationRegister_Default, data:ODCheckerResult): string[] {
- const tm = translation
- const t = {
- headerOpenticket:tm.get("other","opendiscord:header-openticket") ?? "OPEN TICKET",
- headerConfigchecker:tm.get("other","opendiscord:header-configchecker") ?? "CONFIG CHECKER",
- headerDescription:tm.get("other","opendiscord:header-description") ?? "check for errors in your config files!",
- footerError:tm.get("other","opendiscord:footer-error") ?? "the bot won't start until all {0}'s are fixed!",
- footerWarning:tm.get("other","opendiscord:footer-warning") ?? "it's recommended to fix all {0}'s before starting!",
- footerSupport:tm.get("other","opendiscord:footer-support") ?? "SUPPORT: {0} - DOCS: {1}",
- error:tm.get("other","opendiscord:type-error") ?? "[ERROR]",
- warning:tm.get("other","opendiscord:type-warning") ?? "[WARNING]",
- info:tm.get("other","opendiscord:type-info") ?? "[INFO]",
- compactInfo:tm.get("other","opendiscord:compact-information") ?? "use {0} for more information!",
- dataPath:tm.get("other","opendiscord:data-path") ?? "path",
- dataDocs:tm.get("other","opendiscord:data-docs") ?? "docs",
- dataMessage:tm.get("other","opendiscord:data-message") ?? "message"
- }
- const hasErrors = data.messages.filter((m) => m.type == "error").length > 0
- const hasWarnings = data.messages.filter((m) => m.type == "warning").length > 0
- const hasInfo = data.messages.filter((m) => m.type == "info").length > 0
-
- if (!renderEmpty && !hasErrors && !hasWarnings && (!hasInfo || compact)) return []
-
- const headerText = ansis.bold.hex("#f8ba00")(t.headerOpenticket)+" "+t.headerConfigchecker+this.headerSeparator+ansis.hex("#f8ba00")(t.headerDescription)
- const footerErrorText = (hasErrors) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerError,[ansis.bold.red(t.error)])) : ""
- const footerWarningText = (hasWarnings) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerWarning,[ansis.bold.yellow(t.warning)])) : ""
- const footerSupportText = tm.insertTranslationParams(t.footerSupport,[ansis.green("https://discord.dj-dj.be"),ansis.green("https://otdocs.dj-dj.be")])
- const bottomCompactInfo = (compact) ? ansis.gray(tm.insertTranslationParams(t.compactInfo,[ansis.bold.green("npm start -- --checker")])) : ""
-
- const finalHeader = [headerText,...this.extraHeaderText]
- const finalFooter = [footerErrorText,footerWarningText,footerSupportText,...this.extraFooterText]
- const finalTop = [...this.extraTopText]
- const finalBottom = [bottomCompactInfo,...this.extraBottomText]
- const borderLength = this.#getLongestLength([...finalHeader,...finalFooter])
-
- const finalComponents: string[] = []
-
- //header
- if (!this.disableHeader){
- finalHeader.forEach((text) => {
- if (text.length < 1) return
- finalComponents.push(this.#createBlockFromText(text,borderLength))
- })
- }
- finalComponents.push(this.#getHorizontalDivider(borderLength+4))
-
- //top
- finalTop.forEach((text) => {
- if (text.length < 1) return
- finalComponents.push(this.verticalFiller+" "+text)
- })
- finalComponents.push(this.verticalFiller)
-
- //messages
- if (compact){
- //use compact messages
- data.messages.forEach((msg,index) => {
- //compact mode doesn't render info
- if (msg.type == "info") return
-
- //check if translation available & use it if possible
- const rawTranslation = tm.get("message",msg.messageId.value)
- const translatedMessage = (rawTranslation) ? tm.insertTranslationParams(rawTranslation,msg.translationParams) : msg.message
-
- if (msg.type == "error") finalComponents.push(this.verticalFiller+" "+ansis.bold.red(`${t.error} ${translatedMessage}`))
- else if (msg.type == "warning") finalComponents.push(this.verticalFiller+" "+ansis.bold.yellow(`${t.warning} ${translatedMessage}`))
-
- const pathSplitter = msg.path ? ":" : ""
- finalComponents.push(this.verticalFiller+ansis.bold(this.descriptionSeparator)+ansis.cyan(`${ansis.magenta(msg.filepath+pathSplitter)} ${msg.path}`))
- if (index != data.messages.length-1) finalComponents.push(this.verticalFiller)
- })
- }else{
- //use full messages
- data.messages.forEach((msg,index) => {
- //check if translation available & use it if possible
- const rawTranslation = tm.get("message",msg.messageId.value)
- const translatedMessage = (rawTranslation) ? tm.insertTranslationParams(rawTranslation,msg.translationParams) : msg.message
-
- if (msg.type == "error") finalComponents.push(this.verticalFiller+" "+ansis.bold.red(`${t.error} ${translatedMessage}`))
- else if (msg.type == "warning") finalComponents.push(this.verticalFiller+" "+ansis.bold.yellow(`${t.warning} ${translatedMessage}`))
- else if (msg.type == "info") finalComponents.push(this.verticalFiller+" "+ansis.bold.blue(`${t.info} ${translatedMessage}`))
-
- const pathSplitter = msg.path ? ":" : ""
- finalComponents.push(this.verticalFiller+" "+ansis.bold((t.dataPath)+this.descriptionSeparator)+ansis.cyan(`${ansis.magenta(msg.filepath+pathSplitter)} ${msg.path}`))
- if (msg.locationDocs) finalComponents.push(this.verticalFiller+" "+ansis.bold(t.dataDocs+this.descriptionSeparator)+ansis.italic.gray(msg.locationDocs))
- if (msg.messageDocs) finalComponents.push(this.verticalFiller+" "+ansis.bold(t.dataMessage+this.descriptionSeparator)+ansis.italic.gray(msg.messageDocs))
- if (index != data.messages.length-1) finalComponents.push(this.verticalFiller)
- })
- }
-
- //bottom
- finalComponents.push(this.verticalFiller)
- finalBottom.forEach((text) => {
- if (text.length < 1) return
- finalComponents.push(this.verticalFiller+" "+text)
- })
-
- //footer
- finalComponents.push(this.#getHorizontalDivider(borderLength+4))
- if (!this.disableFooter){
- finalFooter.forEach((text) => {
- if (text.length < 1) return
- finalComponents.push(this.#createBlockFromText(text,borderLength))
- })
- finalComponents.push(this.#getHorizontalDivider(borderLength+4))
- }
-
- //return all components
- return finalComponents
- }
- /**Get the length of the longest string in the array. */
- #getLongestLength(texts:string[]): number {
- return Math.max(...texts.map((t) => ansis.strip(t).length))
- }
- /**Get a horizontal divider used between different parts of the config checker result. */
- #getHorizontalDivider(width:number): string {
- if (width > 2) width = width-2
- else return this.verticalFiller+this.verticalFiller
- let divider = this.verticalFiller + this.horizontalFiller.repeat(width) + this.verticalFiller
- return divider
- }
- /**Create a block of text with a vertical divider on the left & right side. */
- #createBlockFromText(text:string,width:number): string {
- if (width < 3) return this.verticalFiller+this.verticalFiller
- let newWidth = width-ansis.strip(text).length+1
- let final = this.verticalFiller+" "+text+" ".repeat(newWidth)+this.verticalFiller
- return final
- }
-}
-
-/**## ODCheckerTranslationRegisterOtherIds_Default `interface`
- * This interface is a list of ids available in the `ODCheckerTranslationRegister_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export type ODCheckerTranslationRegisterOtherIds_Default = (
- "opendiscord:header-openticket"|
- "opendiscord:header-configchecker"|
- "opendiscord:header-description"|
- "opendiscord:type-error"|
- "opendiscord:type-warning"|
- "opendiscord:type-info"|
- "opendiscord:data-path"|
- "opendiscord:data-docs"|
- "opendiscord:data-message"|
- "opendiscord:compact-information"|
- "opendiscord:footer-error"|
- "opendiscord:footer-warning"|
- "opendiscord:footer-support"
-)
-
-/**## ODCheckerTranslationRegisterMessageIds_Default `interface`
- * This interface is a list of ids available in the `ODCheckerTranslationRegister_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export type ODCheckerTranslationRegisterMessageIds_Default = (
- "opendiscord:invalid-type"|
- "opendiscord:property-missing"|
- "opendiscord:property-optional"|
- "opendiscord:object-disabled"|
- "opendiscord:null-invalid"|
- "opendiscord:switch-invalid-type"|
- "opendiscord:object-switch-invalid-type"|
-
- "opendiscord:string-too-short"|
- "opendiscord:string-too-long"|
- "opendiscord:string-length-invalid"|
- "opendiscord:string-starts-with"|
- "opendiscord:string-ends-with"|
- "opendiscord:string-contains"|
- "opendiscord:string-inverted-contains"|
- "opendiscord:string-choices"|
- "opendiscord:string-lowercase"|
- "opendiscord:string-uppercase"|
- "opendiscord:string-special-characters"|
- "opendiscord:string-no-spaces"|
- "opendiscord:string-regex"|
- "opendiscord:string-capital-word"|
- "opendiscord:string-capital-sentence"|
- "opendiscord:string-punctuation"|
-
- "opendiscord:number-nan"|
- "opendiscord:number-too-short"|
- "opendiscord:number-too-long"|
- "opendiscord:number-length-invalid"|
- "opendiscord:number-too-small"|
- "opendiscord:number-too-large"|
- "opendiscord:number-not-equal"|
- "opendiscord:number-step"|
- "opendiscord:number-step-offset"|
- "opendiscord:number-starts-with"|
- "opendiscord:number-ends-with"|
- "opendiscord:number-contains"|
- "opendiscord:number-inverted-contains"|
- "opendiscord:number-choices"|
- "opendiscord:number-float"|
- "opendiscord:number-negative"|
- "opendiscord:number-positive"|
- "opendiscord:number-zero"|
-
- "opendiscord:boolean-true"|
- "opendiscord:boolean-false"|
-
- "opendiscord:array-empty-disabled"|
- "opendiscord:array-empty-required"|
- "opendiscord:array-too-short"|
- "opendiscord:array-too-long"|
- "opendiscord:array-length-invalid"|
- "opendiscord:array-invalid-types"|
- "opendiscord:array-double"|
-
- "opendiscord:discord-invalid-id"|
- "opendiscord:discord-invalid-id-options"|
- "opendiscord:discord-invalid-token"|
- "opendiscord:color-invalid"|
- "opendiscord:emoji-too-short"|
- "opendiscord:emoji-too-long"|
- "opendiscord:emoji-custom"|
- "opendiscord:emoji-invalid"|
- "opendiscord:url-invalid"|
- "opendiscord:url-invalid-http"|
- "opendiscord:url-invalid-protocol"|
- "opendiscord:url-invalid-hostname"|
- "opendiscord:url-invalid-extension"|
- "opendiscord:url-invalid-path"|
- "opendiscord:id-not-unique"|
- "opendiscord:id-non-existent"|
-
- "opendiscord:invalid-language"|
- "opendiscord:invalid-button"|
- "opendiscord:unused-option"|
- "opendiscord:unused-question"|
- "opendiscord:dropdown-option"
-)
-
-/**## ODCheckerTranslationRegister_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODCheckerTranslationRegister class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.checkers.translation`!
- */
-export class ODCheckerTranslationRegister_Default extends ODCheckerTranslationRegister {
- get(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): string
- get(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default): string
- get(type:"message"|"other", id:string): string|null
-
- get(type:"message"|"other", id:string): string|null {
- return super.get(type,id)
- }
-
- set(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default, translation:string): boolean
- set(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default, translation:string): boolean
- set(type:"message"|"other", id:string, translation:string): boolean
-
- set(type:"message"|"other", id:string, translation:string): boolean {
- return super.set(type,id,translation)
- }
-
- delete(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): boolean
- delete(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default): boolean
- delete(type:"message"|"other", id:string): boolean
-
- delete(type:"message"|"other", id:string): boolean {
- return super.delete(type,id)
- }
-
- quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:ODCheckerTranslationRegisterOtherIds_Default|ODCheckerTranslationRegisterMessageIds_Default)
- quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:string)
-
- quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:ODCheckerTranslationRegisterOtherIds_Default|ODCheckerTranslationRegisterMessageIds_Default|string){
- super.quickTranslate(manager,translationId,type,id)
- }
-}
-
-/**## ODCheckerFunctionManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODCheckerFunctionManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODCheckerFunctionManagerIds_Default {
- "opendiscord:unused-options":ODCheckerFunction,
- "opendiscord:unused-questions":ODCheckerFunction,
- "opendiscord:dropdown-options":ODCheckerFunction
-}
-
-/**## ODCheckerFunctionManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODCheckerFunctionManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.checkers.functions`!
- */
-export class ODCheckerFunctionManager_Default extends ODCheckerFunctionManager {
- get(id:CheckerFunctionId): ODCheckerFunctionManagerIds_Default[CheckerFunctionId]
- get(id:ODValidId): ODCheckerFunction|null
-
- get(id:ODValidId): ODCheckerFunction|null {
- return super.get(id)
- }
-
- remove(id:CheckerFunctionId): ODCheckerFunctionManagerIds_Default[CheckerFunctionId]
- remove(id:ODValidId): ODCheckerFunction|null
-
- remove(id:ODValidId): ODCheckerFunction|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODCheckerFunctionManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/client.ts b/src/core/api/defaults/client.ts
deleted file mode 100644
index 7b5a540..0000000
--- a/src/core/api/defaults/client.ts
+++ /dev/null
@@ -1,207 +0,0 @@
-///////////////////////////////////////
-//DEFAULT CLIENT MODULE
-///////////////////////////////////////
-import { ODValidId } from "../modules/base"
-import { ODClientManager, ODSlashCommand, ODTextCommand, ODSlashCommandManager, ODTextCommandManager, ODSlashCommandInteractionCallback, ODTextCommandInteractionCallback, ODContextMenu, ODContextMenuManager, ODContextMenuInteractionCallback } from "../modules/client"
-
-/** (CONTRIBUTOR GUIDE) HOW TO ADD NEW COMMANDS?
- * - Register the command in loadAllSlashCommands() & loadAllTextCommands() in (./src/data/framework/commandLoader.ts)
- * - Add autocomplete for the command in OD(Slash/Text)CommandManagerIds_Default in (./src/core/api/defaults/client.ts)
- * - Add the command to the help menu in (./src/data/framework/helpMenuLoader.ts)
- * - If required, new config variables should be added (incl. logs, dm-logs & permissions).
- * - Update the Open Ticket Documentation.
- * - If the command contains complex logic or can be executed from a button/dropdown, it should be placed inside an `ODAction`.
- * - Check all files, test the bot carefully & try a lot of different scenario's with different settings.
- */
-
-/**## ODClientManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODClientManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.client`!
- */
-export class ODClientManager_Default extends ODClientManager {
- declare slashCommands: ODSlashCommandManager_Default
- declare textCommands: ODTextCommandManager_Default
- declare contextMenus: ODContextMenuManager_Default
-}
-
-/**## ODSlashCommandManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODSlashCommandManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODSlashCommandManagerIds_Default {
- "opendiscord:help":ODSlashCommand,
- "opendiscord:panel":ODSlashCommand,
- "opendiscord:ticket":ODSlashCommand,
- "opendiscord:close":ODSlashCommand,
- "opendiscord:delete":ODSlashCommand,
- "opendiscord:reopen":ODSlashCommand,
- "opendiscord:claim":ODSlashCommand,
- "opendiscord:unclaim":ODSlashCommand,
- "opendiscord:pin":ODSlashCommand,
- "opendiscord:unpin":ODSlashCommand,
- "opendiscord:move":ODSlashCommand,
- "opendiscord:rename":ODSlashCommand,
- "opendiscord:add":ODSlashCommand,
- "opendiscord:remove":ODSlashCommand,
- "opendiscord:blacklist":ODSlashCommand,
- "opendiscord:stats":ODSlashCommand,
- "opendiscord:clear":ODSlashCommand,
- "opendiscord:autoclose":ODSlashCommand,
- "opendiscord:autodelete":ODSlashCommand,
- "opendiscord:topic":ODSlashCommand,
- "opendiscord:priority":ODSlashCommand,
- "opendiscord:transfer":ODSlashCommand,
-}
-
-/**## ODSlashCommandManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODSlashCommandManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.client.slashCommands`!
- */
-export class ODSlashCommandManager_Default extends ODSlashCommandManager {
- get(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId]
- get(id:ODValidId): ODSlashCommand|null
-
- get(id:ODValidId): ODSlashCommand|null {
- return super.get(id)
- }
-
- remove(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId]
- remove(id:ODValidId): ODSlashCommand|null
-
- remove(id:ODValidId): ODSlashCommand|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODSlashCommandManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- onInteraction(commandName:keyof ODSlashCommandManagerIds_Default, callback:ODSlashCommandInteractionCallback): void
- onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback): void
-
- onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback): void {
- return super.onInteraction(commandName,callback)
- }
-}
-
-/**## ODTextCommandManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODTextCommandManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODTextCommandManagerIds_Default {
- "opendiscord:dump":ODTextCommand,
- "opendiscord:help":ODTextCommand,
- "opendiscord:panel":ODTextCommand,
- "opendiscord:close":ODTextCommand,
- "opendiscord:delete":ODTextCommand,
- "opendiscord:reopen":ODTextCommand,
- "opendiscord:claim":ODTextCommand,
- "opendiscord:unclaim":ODTextCommand,
- "opendiscord:pin":ODTextCommand,
- "opendiscord:unpin":ODTextCommand,
- "opendiscord:move":ODTextCommand,
- "opendiscord:rename":ODTextCommand,
- "opendiscord:add":ODTextCommand,
- "opendiscord:remove":ODTextCommand,
- "opendiscord:blacklist-view":ODTextCommand,
- "opendiscord:blacklist-add":ODTextCommand,
- "opendiscord:blacklist-remove":ODTextCommand,
- "opendiscord:blacklist-get":ODTextCommand,
- "opendiscord:stats-global":ODTextCommand,
- "opendiscord:stats-reset":ODTextCommand,
- "opendiscord:stats-ticket":ODTextCommand,
- "opendiscord:stats-user":ODTextCommand,
- "opendiscord:clear":ODTextCommand,
- "opendiscord:autoclose-disable":ODTextCommand,
- "opendiscord:autoclose-enable":ODTextCommand,
- "opendiscord:autodelete-disable":ODTextCommand,
- "opendiscord:autodelete-enable":ODTextCommand,
- "opendiscord:topic-set":ODTextCommand,
- "opendiscord:priority-set":ODTextCommand,
- "opendiscord:priority-get":ODTextCommand,
- "opendiscord:transfer":ODTextCommand,
-}
-
-/**## ODTextCommandManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODTextCommandManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.client.textCommands`!
- */
-export class ODTextCommandManager_Default extends ODTextCommandManager {
- get(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId]
- get(id:ODValidId): ODTextCommand|null
-
- get(id:ODValidId): ODTextCommand|null {
- return super.get(id)
- }
-
- remove(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId]
- remove(id:ODValidId): ODTextCommand|null
-
- remove(id:ODValidId): ODTextCommand|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODTextCommandManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- onInteraction(commandPrefix:string, commandName:string|RegExp, callback:ODTextCommandInteractionCallback): void {
- return super.onInteraction(commandPrefix,commandName,callback)
- }
-}
-
-/**## ODContextMenuManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODContextMenuManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODContextMenuManagerIds_Default {
- //"opendiscord:test-menu":ODContextMenu
-}
-
-/**## ODContextMenuManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODContextMenuManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.client.contextMenus`!
- */
-export class ODContextMenuManager_Default extends ODContextMenuManager {
- get(id:ContextMenuId): ODContextMenuManagerIds_Default[ContextMenuId]
- get(id:ODValidId): ODContextMenu|null
-
- get(id:ODValidId): ODContextMenu|null {
- return super.get(id)
- }
-
- remove(id:ContextMenuId): ODContextMenuManagerIds_Default[ContextMenuId]
- remove(id:ODValidId): ODContextMenu|null
-
- remove(id:ODValidId): ODContextMenu|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODContextMenuManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-
- onInteraction(menuName:keyof ODContextMenuManagerIds_Default, callback:ODContextMenuInteractionCallback): void
- onInteraction(menuName:string|RegExp, callback:ODContextMenuInteractionCallback): void
-
- onInteraction(menuName:string|RegExp, callback:ODContextMenuInteractionCallback): void {
- return super.onInteraction(menuName,callback)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/code.ts b/src/core/api/defaults/code.ts
deleted file mode 100644
index 7ef19a8..0000000
--- a/src/core/api/defaults/code.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-///////////////////////////////////////
-//DEFAULT CODE MODULE
-///////////////////////////////////////
-import { ODValidId } from "../modules/base"
-import { ODCode, ODCodeManager } from "../modules/code"
-
-/**## ODCodeManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODCodeManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODCodeManagerIds_Default {
- "opendiscord:command-error-handling":ODCode,
- "opendiscord:start-listening-interactions":ODCode,
- "opendiscord:panel-database-cleaner":ODCode,
- "opendiscord:suffix-database-cleaner":ODCode,
- "opendiscord:option-database-cleaner":ODCode,
- "opendiscord:user-database-cleaner":ODCode,
- "opendiscord:ticket-database-cleaner":ODCode,
- "opendiscord:panel-auto-update":ODCode,
- "opendiscord:ticket-saver":ODCode,
- "opendiscord:blacklist-saver":ODCode,
- "opendiscord:auto-role-on-join":ODCode,
- "opendiscord:autoclose-timeout":ODCode,
- "opendiscord:autoclose-leave":ODCode,
- "opendiscord:autodelete-timeout":ODCode,
- "opendiscord:autodelete-leave":ODCode,
- "opendiscord:ticket-anti-busy":ODCode,
-}
-
-/**## ODCodeManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODCodeManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.code`!
- */
-export class ODCodeManager_Default extends ODCodeManager {
- get(id:CodeId): ODCodeManagerIds_Default[CodeId]
- get(id:ODValidId): ODCode|null
-
- get(id:ODValidId): ODCode|null {
- return super.get(id)
- }
-
- remove(id:CodeId): ODCodeManagerIds_Default[CodeId]
- remove(id:ODValidId): ODCode|null
-
- remove(id:ODValidId): ODCode|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODCodeManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/console.ts b/src/core/api/defaults/console.ts
deleted file mode 100644
index 6b4d0da..0000000
--- a/src/core/api/defaults/console.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-///////////////////////////////////////
-//DEFAULT CONSOLE MODULE
-///////////////////////////////////////
-import { ODValidId } from "../modules/base"
-import { ODLiveStatusUrlSource, ODLiveStatusManager, ODLiveStatusSource } from "../modules/console"
-
-/**## ODLiveStatusManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODLiveStatusManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODLiveStatusManagerIds_Default {
- "opendiscord:default-djdj-dev":ODLiveStatusUrlSource
-}
-
-/**## ODLiveStatusManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODLiveStatusManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.livestatus`!
- */
-export class ODLiveStatusManager_Default extends ODLiveStatusManager {
- get(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId]
- get(id:ODValidId): ODLiveStatusSource|null
-
- get(id:ODValidId): ODLiveStatusSource|null {
- return super.get(id)
- }
-
- remove(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId]
- remove(id:ODValidId): ODLiveStatusSource|null
-
- remove(id:ODValidId): ODLiveStatusSource|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODLiveStatusManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/cooldown.ts b/src/core/api/defaults/cooldown.ts
deleted file mode 100644
index 75a53e7..0000000
--- a/src/core/api/defaults/cooldown.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-///////////////////////////////////////
-//DEFAULT COOLDOWN MODULE
-///////////////////////////////////////
-import { ODValidId } from "../modules/base"
-import { ODCooldown, ODCooldownManager } from "../modules/cooldown"
-
-/**## ODCooldownManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODCooldownManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODCooldownManagerIds_Default {
-
-}
-
-/**## ODCooldownManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODCooldownManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.cooldowns`!
- */
-export class ODCooldownManager_Default extends ODCooldownManager {
- get(id:CooldownId): ODCooldownManagerIds_Default[CooldownId]
- get(id:ODValidId): ODCooldown|null
-
- get(id:ODValidId): ODCooldown|null {
- return super.get(id)
- }
-
- remove(id:CooldownId): ODCooldownManagerIds_Default[CooldownId]
- remove(id:ODValidId): ODCooldown|null
-
- remove(id:ODValidId): ODCooldown|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODCooldownManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/database.ts b/src/core/api/defaults/database.ts
deleted file mode 100644
index 8e73a10..0000000
--- a/src/core/api/defaults/database.ts
+++ /dev/null
@@ -1,257 +0,0 @@
-///////////////////////////////////////
-//DEFAULT DATABASE MODULE
-///////////////////////////////////////
-import { ODOptionalPromise, ODValidId, ODValidJsonType } from "../modules/base"
-import { ODDatabaseManager, ODDatabase, ODFormattedJsonDatabase } from "../modules/database"
-import { ODTicketJson } from "../openticket/ticket"
-import { ODOptionJson } from "../openticket/option"
-
-/**## ODDatabaseManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODDatabaseManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODDatabaseManagerIds_Default {
- "opendiscord:global":ODFormattedJsonDatabase_DefaultGlobal,
- "opendiscord:stats":ODFormattedJsonDatabase,
- "opendiscord:tickets":ODFormattedJsonDatabase_DefaultTickets,
- "opendiscord:users":ODFormattedJsonDatabase_DefaultUsers,
- "opendiscord:options":ODFormattedJsonDatabase_DefaultOptions,
-}
-
-/**## ODDatabaseManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODDatabaseManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.databases`!
- */
-export class ODDatabaseManager_Default extends ODDatabaseManager {
- get(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId]
- get(id:ODValidId): ODDatabase|null
-
- get(id:ODValidId): ODDatabase|null {
- return super.get(id)
- }
-
- remove(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId]
- remove(id:ODValidId): ODDatabase|null
-
- remove(id:ODValidId): ODDatabase|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODDatabaseManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
-
-/**## ODFormattedJsonDatabaseIds_DefaultGlobal `type`
- * This interface is a list of ids available in the `ODFormattedJsonDatabase_DefaultGlobal` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODFormattedJsonDatabaseIds_DefaultGlobal {
- "opendiscord:panel-message":string,
- "opendiscord:panel-update":string,
- "opendiscord:option-suffix-counter":number,
- "opendiscord:option-suffix-history":string[],
- "opendiscord:last-version":string
-}
-
-/**## ODFormattedJsonDatabase_DefaultGlobal `default_class`
- * This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `global.json` database!
- */
-export class ODFormattedJsonDatabase_DefaultGlobal extends ODFormattedJsonDatabase {
- set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]): ODOptionalPromise
- set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise
-
- set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise {
- return super.set(category,key,value)
- }
-
- get(category:CategoryId, key:string): ODOptionalPromise
- get(category:string, key:string): ODOptionalPromise
-
- get(category:string, key:string): ODOptionalPromise {
- return super.get(category,key)
- }
-
- delete(category:CategoryId, key:string): ODOptionalPromise
- delete(category:string, key:string): ODOptionalPromise
-
- delete(category:string, key:string): ODOptionalPromise {
- return super.delete(category,key)
- }
-
- exists(category:keyof ODFormattedJsonDatabaseIds_DefaultGlobal, key:string): ODOptionalPromise
- exists(category:string, key:string): ODOptionalPromise
-
- exists(category:string, key:string): ODOptionalPromise {
- return super.exists(category,key)
- }
-
- getCategory(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]}[]|undefined>
- getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined>
-
- getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
- return super.getCategory(category)
- }
-}
-
-/**## ODFormattedJsonDatabaseIds_DefaultTickets `type`
- * This interface is a list of ids available in the `ODDatabaseManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODFormattedJsonDatabaseIds_DefaultTickets {
- "opendiscord:ticket":ODTicketJson
-}
-
-/**## ODFormattedJsonDatabase_DefaultTickets `default_class`
- * This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `tickets.json` database!
- */
-export class ODFormattedJsonDatabase_DefaultTickets extends ODFormattedJsonDatabase {
- set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]): ODOptionalPromise
- set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise
-
- set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise {
- return super.set(category,key,value)
- }
-
- get(category:CategoryId, key:string): ODOptionalPromise
- get(category:string, key:string): ODOptionalPromise
-
- get(category:string, key:string): ODOptionalPromise {
- return super.get(category,key)
- }
-
- delete(category:CategoryId, key:string): ODOptionalPromise
- delete(category:string, key:string): ODOptionalPromise
-
- delete(category:string, key:string): ODOptionalPromise {
- return super.delete(category,key)
- }
-
- exists(category:keyof ODFormattedJsonDatabaseIds_DefaultTickets, key:string): ODOptionalPromise
- exists(category:string, key:string): ODOptionalPromise
-
- exists(category:string, key:string): ODOptionalPromise {
- return super.exists(category,key)
- }
-
- getCategory(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]}[]|undefined>
- getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined>
-
- getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
- return super.getCategory(category)
- }
-}
-
-/**## ODFormattedJsonDatabaseIds_DefaultUsers `type`
- * This interface is a list of ids available in the `ODDatabaseManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODFormattedJsonDatabaseIds_DefaultUsers {
- "opendiscord:blacklist":ODTicketJson
-}
-
-/**## ODFormattedJsonDatabase_DefaultUsers `default_class`
- * This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `users.json` database!
- */
-export class ODFormattedJsonDatabase_DefaultUsers extends ODFormattedJsonDatabase {
- set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]): ODOptionalPromise
- set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise
-
- set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise {
- return super.set(category,key,value)
- }
-
- get(category:CategoryId, key:string): ODOptionalPromise
- get(category:string, key:string): ODOptionalPromise
-
- get(category:string, key:string): ODOptionalPromise {
- return super.get(category,key)
- }
-
- delete(category:CategoryId, key:string): ODOptionalPromise
- delete(category:string, key:string): ODOptionalPromise
-
- delete(category:string, key:string): ODOptionalPromise {
- return super.delete(category,key)
- }
-
- exists(category:keyof ODFormattedJsonDatabaseIds_DefaultUsers, key:string): ODOptionalPromise
- exists(category:string, key:string): ODOptionalPromise
-
- exists(category:string, key:string): ODOptionalPromise {
- return super.exists(category,key)
- }
-
- getCategory(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]}[]|undefined>
- getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined>
-
- getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
- return super.getCategory(category)
- }
-}
-
-
-/**## ODFormattedJsonDatabaseIds_DefaultOptions `type`
- * This interface is a list of ids available in the `ODDatabaseManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODFormattedJsonDatabaseIds_DefaultOptions {
- "opendiscord:used-option":ODOptionJson
-}
-
-/**## ODFormattedJsonDatabase_DefaultOptions `default_class`
- * This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `options.json` database!
- */
-export class ODFormattedJsonDatabase_DefaultOptions extends ODFormattedJsonDatabase {
- set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]): ODOptionalPromise
- set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise
-
- set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise {
- return super.set(category,key,value)
- }
-
- get(category:CategoryId, key:string): ODOptionalPromise
- get(category:string, key:string): ODOptionalPromise
-
- get(category:string, key:string): ODOptionalPromise {
- return super.get(category,key)
- }
-
- delete(category:CategoryId, key:string): ODOptionalPromise
- delete(category:string, key:string): ODOptionalPromise
-
- delete(category:string, key:string): ODOptionalPromise {
- return super.delete(category,key)
- }
-
- exists(category:keyof ODFormattedJsonDatabaseIds_DefaultOptions, key:string): ODOptionalPromise
- exists(category:string, key:string): ODOptionalPromise
-
- exists(category:string, key:string): ODOptionalPromise {
- return super.exists(category,key)
- }
-
- getCategory(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]}[]|undefined>
- getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined>
-
- getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
- return super.getCategory(category)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts
deleted file mode 100644
index 86496fc..0000000
--- a/src/core/api/defaults/event.ts
+++ /dev/null
@@ -1,390 +0,0 @@
-///////////////////////////////////////
-//DEFAULT EVENT MODULE
-///////////////////////////////////////
-//BASE MODULES
-import { ODPromiseVoid, ODValidId } from "../modules/base"
-import { ODConsoleManager, ODError } from "../modules/console"
-import { ODCheckerResult, ODCheckerStorage } from "../modules/checker"
-import { ODDefaultsManager } from "../modules/defaults"
-import { ODLanguage } from "../modules/language"
-import { ODClientActivityManager } from "../modules/client"
-import { ODEvent, ODEventManager } from "../modules/event"
-import * as discord from "discord.js"
-
-//DEFAULT MODULES
-import { ODPluginClassManager_Default, ODPluginManager_Default } from "./plugin"
-import { ODConfigManager_Default} from "./config"
-import { ODDatabaseManager_Default } from "./database"
-import { ODFlagManager_Default } from "./flag"
-import { ODSessionManager_Default } from "./session"
-import { ODLanguageManager_Default } from "./language"
-import { ODCheckerFunctionManager_Default, ODCheckerManager_Default, ODCheckerRenderer_Default, ODCheckerTranslationRegister_Default } from "./checker"
-import { ODClientManager_Default, ODContextMenuManager_Default, ODSlashCommandManager_Default, ODTextCommandManager_Default } from "./client"
-import { ODBuilderManager_Default, ODButtonManager_Default, ODDropdownManager_Default, ODEmbedManager_Default, ODFileManager_Default, ODMessageManager_Default, ODModalManager_Default } from "./builder"
-import { ODAutocompleteResponderManager_Default, ODButtonResponderManager_Default, ODCommandResponderManager_Default, ODContextMenuResponderManager_Default, ODDropdownResponderManager_Default, ODModalResponderManager_Default, ODResponderManager_Default } from "./responder"
-import { ODActionManager_Default } from "./action"
-import { ODPermissionManager_Default } from "./permission"
-import { ODHelpMenuManager_Default } from "./helpmenu"
-import { ODStatsManager_Default } from "./stat"
-import { ODCodeManager_Default } from "./code"
-import { ODCooldownManager_Default } from "./cooldown"
-import { ODPostManager_Default } from "./post"
-import { ODVerifyBarManager_Default } from "./verifybar"
-import { ODStartScreenManager_Default } from "./startscreen"
-import { ODLiveStatusManager_Default } from "./console"
-import { ODProgressBarManager_Default, ODProgressBarRendererManager_Default } from "./progressbar"
-
-//OPEN TICKET MODULES
-import { ODOptionManager, ODTicketOption } from "../openticket/option"
-import { ODPanel, ODPanelManager } from "../openticket/panel"
-import { ODTicket, ODTicketClearFilter, ODTicketManager } from "../openticket/ticket"
-import { ODQuestionManager } from "../openticket/question"
-import { ODBlacklistManager } from "../openticket/blacklist"
-import { ODTranscriptManager_Default } from "../openticket/transcript"
-import { ODRole, ODRoleManager } from "../openticket/role"
-import { ODPriorityLevel, ODPriorityManager_Default } from "../openticket/priority"
-
-/**## ODEventIds_Default `interface`
- * This interface is a list of ids available in the `ODEvent_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODEventIds_Default {
- //error handling
- "onErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin) => ODPromiseVoid>
- "afterErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin, message:ODError) => ODPromiseVoid>
-
- //plugins
- "afterPluginsLoaded": ODEvent_Default<(plugins:ODPluginManager_Default) => ODPromiseVoid>
- "onPluginClassLoad": ODEvent_Default<(classes:ODPluginClassManager_Default, plugins:ODPluginManager_Default) => ODPromiseVoid>
- "afterPluginClassesLoaded": ODEvent_Default<(classes:ODPluginClassManager_Default, plugins:ODPluginManager_Default) => ODPromiseVoid>
-
- //flags
- "onFlagLoad": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
- "afterFlagsLoaded": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
- "onFlagInit": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
- "afterFlagsInitiated": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
-
- //progress bars
- "onProgressBarRendererLoad": ODEvent_Default<(renderers:ODProgressBarRendererManager_Default) => ODPromiseVoid>
- "afterProgressBarRenderersLoaded": ODEvent_Default<(renderers:ODProgressBarRendererManager_Default) => ODPromiseVoid>
- "onProgressBarLoad": ODEvent_Default<(progressbars:ODProgressBarManager_Default) => ODPromiseVoid>
- "afterProgressBarsLoaded": ODEvent_Default<(progressbars:ODProgressBarManager_Default) => ODPromiseVoid>
-
- //configs
- "onConfigLoad": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
- "afterConfigsLoaded": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
- "onConfigInit": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
- "afterConfigsInitiated": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
-
- //databases
- "onDatabaseLoad": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
- "afterDatabasesLoaded": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
- "onDatabaseInit": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
- "afterDatabasesInitiated": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
-
- //languages
- "onLanguageLoad": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
- "afterLanguagesLoaded": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
- "onLanguageInit": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
- "afterLanguagesInitiated": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
- "onLanguageSelect": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
- "afterLanguagesSelected": ODEvent_Default<(main:ODLanguage|null, backup:ODLanguage|null, languages:ODLanguageManager_Default) => ODPromiseVoid>
-
- //sessions
- "onSessionLoad": ODEvent_Default<(languages:ODSessionManager_Default) => ODPromiseVoid>
- "afterSessionsLoaded": ODEvent_Default<(languages:ODSessionManager_Default) => ODPromiseVoid>
-
- //config checkers
- "onCheckerLoad": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "afterCheckersLoaded": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "onCheckerFunctionLoad": ODEvent_Default<(functions:ODCheckerFunctionManager_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "afterCheckerFunctionsLoaded": ODEvent_Default<(functions:ODCheckerFunctionManager_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "onCheckerExecute": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "afterCheckersExecuted": ODEvent_Default<(result:ODCheckerResult, checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "onCheckerTranslationLoad": ODEvent_Default<(translations:ODCheckerTranslationRegister_Default, enabled:boolean, checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "afterCheckerTranslationsLoaded": ODEvent_Default<(translations:ODCheckerTranslationRegister_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "onCheckerRender": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "afterCheckersRendered": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
- "onCheckerQuit": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
-
- //plugin loading before client
- "onPluginBeforeClientLoad": ODEvent_Default<() => ODPromiseVoid>,
- "afterPluginBeforeClientLoaded": ODEvent_Default<() => ODPromiseVoid>,
-
- //client configuration
- "onClientLoad": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
- "afterClientLoaded": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
- "onClientInit": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
- "afterClientInitiated": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
- "onClientReady": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
- "afterClientReady": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
- "onClientActivityLoad": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
- "afterClientActivityLoaded": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
- "onClientActivityInit": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
- "afterClientActivityInitiated": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
-
- //priority levels
- "onPriorityLoad": ODEvent_Default<(priorities:ODPriorityManager_Default) => ODPromiseVoid>
- "afterPrioritiesLoaded": ODEvent_Default<(priorities:ODPriorityManager_Default) => ODPromiseVoid>
-
- //client slash commands
- "onSlashCommandLoad": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
- "afterSlashCommandsLoaded": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
- "onSlashCommandRegister": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
- "afterSlashCommandsRegistered": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
-
- //client context menus
- "onContextMenuLoad": ODEvent_Default<(menu:ODContextMenuManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
- "afterContextMenusLoaded": ODEvent_Default<(menu:ODContextMenuManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
- "onContextMenuRegister": ODEvent_Default<(menu:ODContextMenuManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
- "afterContextMenusRegistered": ODEvent_Default<(menu:ODContextMenuManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
-
- //client text commands
- "onTextCommandLoad": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default,) => ODPromiseVoid>
- "afterTextCommandsLoaded": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
-
- //plugin loading before managers
- "onPluginBeforeManagerLoad": ODEvent_Default<() => ODPromiseVoid>,
- "afterPluginBeforeManagerLoaded": ODEvent_Default<() => ODPromiseVoid>,
-
- //questions
- "onQuestionLoad": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid>
- "afterQuestionsLoaded": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid>
-
- //options
- "onOptionLoad": ODEvent_Default<(options:ODOptionManager) => ODPromiseVoid>
- "afterOptionsLoaded": ODEvent_Default<(options:ODOptionManager) => ODPromiseVoid>
-
- //panels
- "onPanelLoad": ODEvent_Default<(panels:ODPanelManager) => ODPromiseVoid>
- "afterPanelsLoaded": ODEvent_Default<(panels:ODPanelManager) => ODPromiseVoid>
- "onPanelSpawn": ODEvent_Default<(panel:ODPanel) => ODPromiseVoid>
- "afterPanelSpawned": ODEvent_Default<(panel:ODPanel) => ODPromiseVoid>
-
- //tickets
- "onTicketLoad": ODEvent_Default<(tickets:ODTicketManager) => ODPromiseVoid>
- "afterTicketsLoaded": ODEvent_Default<(tickets:ODTicketManager) => ODPromiseVoid>
-
- //ticket creation
- "onTicketChannelCreation": ODEvent_Default<(option:ODTicketOption, user:discord.User) => ODPromiseVoid>
- "afterTicketChannelCreated": ODEvent_Default<(option:ODTicketOption, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
- "onTicketChannelDeletion": ODEvent_Default<(ticket:ODTicket, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
- "afterTicketChannelDeleted": ODEvent_Default<(ticket:ODTicket, user:discord.User) => ODPromiseVoid>
- "onTicketPermissionsCreated": ODEvent_Default<(option:ODTicketOption, permissions:ODPermissionManager_Default, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
- "afterTicketPermissionsCreated": ODEvent_Default<(option:ODTicketOption, permissions:ODPermissionManager_Default, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
- "onTicketMainMessageCreated": ODEvent_Default<(ticket:ODTicket, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
- "afterTicketMainMessageCreated": ODEvent_Default<(ticket:ODTicket, message:discord.Message, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
-
- //ticket actions
- "onTicketCreate": ODEvent_Default<(creator:discord.User) => ODPromiseVoid>
- "afterTicketCreated": ODEvent_Default<(ticket:ODTicket, creator:discord.User, channel:discord.GuildTextBasedChannel) => ODPromiseVoid>
- "onTicketClose": ODEvent_Default<(ticket:ODTicket, closer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketClosed": ODEvent_Default<(ticket:ODTicket, closer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketReopen": ODEvent_Default<(ticket:ODTicket, reopener:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketReopened": ODEvent_Default<(ticket:ODTicket, reopener:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketDelete": ODEvent_Default<(ticket:ODTicket, deleter:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketDeleted": ODEvent_Default<(ticket:ODTicket, deleter:discord.User, reason:string|null) => ODPromiseVoid>
- "onTicketMove": ODEvent_Default<(ticket:ODTicket, mover:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketMoved": ODEvent_Default<(ticket:ODTicket, mover:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketClaim": ODEvent_Default<(ticket:ODTicket, claimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketClaimed": ODEvent_Default<(ticket:ODTicket, claimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketUnclaim": ODEvent_Default<(ticket:ODTicket, unclaimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketUnclaimed": ODEvent_Default<(ticket:ODTicket, unclaimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketPin": ODEvent_Default<(ticket:ODTicket, pinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketPinned": ODEvent_Default<(ticket:ODTicket, pinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketUnpin": ODEvent_Default<(ticket:ODTicket, unpinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketUnpinned": ODEvent_Default<(ticket:ODTicket, unpinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketUserAdd": ODEvent_Default<(ticket:ODTicket, adder:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketUserAdded": ODEvent_Default<(ticket:ODTicket, adder:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketUserRemove": ODEvent_Default<(ticket:ODTicket, remover:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketUserRemoved": ODEvent_Default<(ticket:ODTicket, remover:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketRename": ODEvent_Default<(ticket:ODTicket, renamer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "afterTicketRenamed": ODEvent_Default<(ticket:ODTicket, renamer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
- "onTicketsClear": ODEvent_Default<(tickets:ODTicket[], clearer:discord.User, channel:discord.GuildTextBasedChannel, filter:ODTicketClearFilter) => ODPromiseVoid>
- "afterTicketsCleared": ODEvent_Default<(tickets:ODTicket[], clearer:discord.User, channel:discord.GuildTextBasedChannel, filter:ODTicketClearFilter) => ODPromiseVoid>
- "onTicketTopicChange": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldTopic:string, newTopic:string) => ODPromiseVoid>
- "afterTicketTopicChanged": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldTopic:string, newTopic:string) => ODPromiseVoid>
- "onTicketPriorityChange": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldPriority:ODPriorityLevel, newPriority:ODPriorityLevel, reason:string|null) => ODPromiseVoid>
- "afterTicketPriorityChanged": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldPriority:ODPriorityLevel, newPriority:ODPriorityLevel, reason:string|null) => ODPromiseVoid>
- "onTicketTransfer": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldCreator:discord.User, newCreator:discord.User, reason:string|null) => ODPromiseVoid>
- "afterTicketTransferred": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldCreator:discord.User, newCreator:discord.User, reason:string|null) => ODPromiseVoid>
-
- //roles
- "onRoleLoad": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid>
- "afterRolesLoaded": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid>
- "onRoleUpdate": ODEvent_Default<(user:discord.User,role:ODRole) => ODPromiseVoid>
- "afterRolesUpdated": ODEvent_Default<(user:discord.User,role:ODRole) => ODPromiseVoid>
-
- //blacklist
- "onBlacklistLoad": ODEvent_Default<(blacklist:ODBlacklistManager) => ODPromiseVoid>
- "afterBlacklistLoaded": ODEvent_Default<(blacklist:ODBlacklistManager) => ODPromiseVoid>
-
- //transcripts
- "onTranscriptCompilerLoad": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
- "afterTranscriptCompilersLoaded": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
- "onTranscriptHistoryLoad": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
- "afterTranscriptHistoryLoaded": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
-
- //transcript creation
- "onTranscriptCreate": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
- "afterTranscriptCreated": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
- "onTranscriptInit": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
- "afterTranscriptInitiated": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
- "onTranscriptCompile": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
- "afterTranscriptCompiled": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
- "onTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
- "afterTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
-
- //plugin loading before builders
- "onPluginBeforeBuilderLoad": ODEvent_Default<() => ODPromiseVoid>,
- "afterPluginBeforeBuilderLoaded": ODEvent_Default<() => ODPromiseVoid>,
-
- //builders
- "onButtonBuilderLoad": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterButtonBuildersLoaded": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onDropdownBuilderLoad": ODEvent_Default<(dropdowns:ODDropdownManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterDropdownBuildersLoaded": ODEvent_Default<(dropdowns:ODDropdownManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onFileBuilderLoad": ODEvent_Default<(files:ODFileManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterFileBuildersLoaded": ODEvent_Default<(files:ODFileManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onEmbedBuilderLoad": ODEvent_Default<(embeds:ODEmbedManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterEmbedBuildersLoaded": ODEvent_Default<(embeds:ODEmbedManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onMessageBuilderLoad": ODEvent_Default<(messages:ODMessageManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterMessageBuildersLoaded": ODEvent_Default<(messages:ODMessageManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onModalBuilderLoad": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterModalBuildersLoaded": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
-
- //plugin loading before responders
- "onPluginBeforeResponderLoad": ODEvent_Default<() => ODPromiseVoid>,
- "afterPluginBeforeResponderLoaded": ODEvent_Default<() => ODPromiseVoid>,
-
- //responders
- "onCommandResponderLoad": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterCommandRespondersLoaded": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onButtonResponderLoad": ODEvent_Default<(buttons:ODButtonResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterButtonRespondersLoaded": ODEvent_Default<(buttons:ODButtonResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onDropdownResponderLoad": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterDropdownRespondersLoaded": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onModalResponderLoad": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterModalRespondersLoaded": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onContextMenuResponderLoad": ODEvent_Default<(menus:ODContextMenuResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterContextMenuRespondersLoaded": ODEvent_Default<(menus:ODContextMenuResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "onAutocompleteResponderLoad": ODEvent_Default<(autocomplete:ODAutocompleteResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
- "afterAutocompleteRespondersLoaded": ODEvent_Default<(autocomplete:ODAutocompleteResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
-
- //plugin loading before finalizations
- "onPluginBeforeFinalizationLoad": ODEvent_Default<() => ODPromiseVoid>,
- "afterPluginBeforeFinalizationLoaded": ODEvent_Default<() => ODPromiseVoid>,
-
- //actions
- "onActionLoad": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid>
- "afterActionsLoaded": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid>
-
- //verifybars
- "onVerifyBarLoad": ODEvent_Default<(verifybars:ODVerifyBarManager_Default) => ODPromiseVoid>
- "afterVerifyBarsLoaded": ODEvent_Default<(verifybars:ODVerifyBarManager_Default) => ODPromiseVoid>
-
- //permissions
- "onPermissionLoad": ODEvent_Default<(permissions:ODPermissionManager_Default) => ODPromiseVoid>
- "afterPermissionsLoaded": ODEvent_Default<(permissions:ODPermissionManager_Default) => ODPromiseVoid>
-
- //posts
- "onPostLoad": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
- "afterPostsLoaded": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
- "onPostInit": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
- "afterPostsInitiated": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
-
- //cooldowns
- "onCooldownLoad": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
- "afterCooldownsLoaded": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
- "onCooldownInit": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
- "afterCooldownsInitiated": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
-
- //help menu
- "onHelpMenuCategoryLoad": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
- "afterHelpMenuCategoriesLoaded": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
- "onHelpMenuComponentLoad": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
- "afterHelpMenuComponentsLoaded": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
-
- //stats
- "onStatScopeLoad": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
- "afterStatScopesLoaded": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
- "onStatLoad": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
- "afterStatsLoaded": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
- "onStatInit": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
- "afterStatsInitiated": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
-
- //plugin loading before code
- "onPluginBeforeCodeLoad": ODEvent_Default<() => ODPromiseVoid>,
- "afterPluginBeforeCodeLoaded": ODEvent_Default<() => ODPromiseVoid>,
-
- //code
- "onCodeLoad": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
- "afterCodeLoaded": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
- "onCodeExecute": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
- "afterCodeExecuted": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
-
- //livestatus
- "onLiveStatusSourceLoad": ODEvent_Default<(livestatus:ODLiveStatusManager_Default) => ODPromiseVoid>
- "afterLiveStatusSourcesLoaded": ODEvent_Default<(livestatus:ODLiveStatusManager_Default) => ODPromiseVoid>
-
- //startscreen
- "onStartScreenLoad": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
- "afterStartScreensLoaded": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
- "onStartScreenRender": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
- "afterStartScreensRendered": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
-
- //ready
- "beforeReadyForUsage": ODEvent_Default<() => ODPromiseVoid>
- "onReadyForUsage": ODEvent_Default<() => ODPromiseVoid>
-}
-
-/**## ODEventManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODEvent class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.events`!
- */
-export class ODEventManager_Default extends ODEventManager {
- get(id:StartScreenId): ODEventIds_Default[StartScreenId]
- get(id:ODValidId): ODEvent|null
-
- get(id:ODValidId): ODEvent|null {
- return super.get(id)
- }
-
- remove(id:StartScreenId): ODEventIds_Default[StartScreenId]
- remove(id:ODValidId): ODEvent|null
-
- remove(id:ODValidId): ODEvent|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODEventIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
-
-/**## ODEventManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODEvent class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.events`!
- */
-export class ODEvent_Default ODPromiseVoid)> extends ODEvent {
- listen(callback:Callback): void {
- return super.listen(callback)
- }
- listenOnce(callback:Callback): void {
- return super.listenOnce(callback)
- }
- wait(): Promise>
- wait(): Promise {
- return super.wait()
- }
- emit(params:Parameters): Promise {
- return super.emit(params)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/flag.ts b/src/core/api/defaults/flag.ts
deleted file mode 100644
index 8830cc2..0000000
--- a/src/core/api/defaults/flag.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-///////////////////////////////////////
-//DEFAULT PROCESS MODULE
-///////////////////////////////////////
-import { ODValidId } from "../modules/base"
-import { ODFlagManager, ODFlag } from "../modules/flag"
-
-/**## ODFlagManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODFlagManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODFlagManagerIds_Default {
- "opendiscord:no-migration":ODFlag,
- "opendiscord:dev-config":ODFlag,
- "opendiscord:dev-database":ODFlag,
- "opendiscord:debug":ODFlag,
- "opendiscord:crash":ODFlag,
- "opendiscord:no-transcripts":ODFlag,
- "opendiscord:no-checker":ODFlag,
- "opendiscord:checker":ODFlag,
- "opendiscord:no-easter":ODFlag,
- "opendiscord:no-plugins":ODFlag,
- "opendiscord:soft-plugins":ODFlag,
- "opendiscord:force-slash-update":ODFlag,
- "opendiscord:no-compile":ODFlag,
- "opendiscord:compile-only":ODFlag,
- "opendiscord:silent":ODFlag,
- "opendiscord:cli":ODFlag,
-}
-
-/**## ODFlagManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODFlagManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.flags`!
- */
-export class ODFlagManager_Default extends ODFlagManager {
- get(id:FlagId): ODFlagManagerIds_Default[FlagId]
- get(id:ODValidId): ODFlag|null
-
- get(id:ODValidId): ODFlag|null {
- return super.get(id)
- }
-
- remove(id:FlagId): ODFlagManagerIds_Default[FlagId]
- remove(id:ODValidId): ODFlag|null
-
- remove(id:ODValidId): ODFlag|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODFlagManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
\ No newline at end of file
diff --git a/src/core/api/defaults/helpmenu.ts b/src/core/api/defaults/helpmenu.ts
deleted file mode 100644
index 9864f18..0000000
--- a/src/core/api/defaults/helpmenu.ts
+++ /dev/null
@@ -1,338 +0,0 @@
-///////////////////////////////////////
-//DEFAULT HELP MODULE
-///////////////////////////////////////
-import { ODValidId } from "../modules/base"
-import { ODHelpMenuCategory, ODHelpMenuCommandComponent, ODHelpMenuComponent, ODHelpMenuManager } from "../modules/helpmenu"
-
-/** (CONTRIBUTOR GUIDE) HOW TO ADD NEW COMMANDS?
- * - Register the command in loadAllSlashCommands() & loadAllTextCommands() in (./src/data/framework/commandLoader.ts)
- * - Add autocomplete for the command in OD(Slash/Text)CommandManagerIds_Default in (./src/core/api/defaults/client.ts)
- * - Add the command to the help menu in (./src/data/framework/helpMenuLoader.ts)
- * - If required, new config variables should be added (incl. logs, dm-logs & permissions).
- * - Update the Open Ticket Documentation.
- * - If the command contains complex logic or can be executed from a button/dropdown, it should be placed inside an `ODAction`.
- * - Check all files, test the bot carefully & try a lot of different scenario's with different settings.
- */
-
-/**## ODHelpMenuManagerIds_Default `interface`
- * This interface is a list of ids available in the `ODHelpMenuManager_Default` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODHelpMenuManagerIds_Default {
- "opendiscord:general":ODHelpMenuCategory_DefaultGeneral,
- "opendiscord:ticket-basic":ODHelpMenuCategory_DefaultTicketBasic,
- "opendiscord:ticket-advanced":ODHelpMenuCategory_DefaultTicketAdvanced,
- "opendiscord:ticket-user":ODHelpMenuCategory_DefaultTicketUser,
- "opendiscord:admin":ODHelpMenuCategory_DefaultAdmin,
- "opendiscord:advanced":ODHelpMenuCategory_DefaultAdvanced,
- "opendiscord:extra":ODHelpMenuCategory_DefaultExtra
-}
-
-/**## ODHelpMenuManager_Default `default_class`
- * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the global variable `opendiscord.helpmenu`!
- */
-export class ODHelpMenuManager_Default extends ODHelpMenuManager {
- get(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId]
- get(id:ODValidId): ODHelpMenuCategory|null
-
- get(id:ODValidId): ODHelpMenuCategory|null {
- return super.get(id)
- }
-
- remove(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId]
- remove(id:ODValidId): ODHelpMenuCategory|null
-
- remove(id:ODValidId): ODHelpMenuCategory|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODHelpMenuManagerIds_Default): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
-
-/**## ODHelpMenuManagerCategoryIds_DefaultGeneral `type`
- * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultGeneral` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODHelpMenuManagerCategoryIds_DefaultGeneral {
- "opendiscord:help":ODHelpMenuCommandComponent,
- "opendiscord:ticket":ODHelpMenuCommandComponent|null
-}
-
-/**## ODHelpMenuCategory_DefaultGeneral `default_class`
- * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `opendiscord:general` category in `opendiscord.helpmenu`!
- */
-export class ODHelpMenuCategory_DefaultGeneral extends ODHelpMenuCategory {
- get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId]
- get(id:ODValidId): ODHelpMenuComponent|null
-
- get(id:ODValidId): ODHelpMenuComponent|null {
- return super.get(id)
- }
-
- remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId]
- remove(id:ODValidId): ODHelpMenuComponent|null
-
- remove(id:ODValidId): ODHelpMenuComponent|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultGeneral): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
-
-/**## ODHelpMenuManagerCategoryIds_DefaultTicketBasic `type`
- * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketBasic` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODHelpMenuManagerCategoryIds_DefaultTicketBasic {
- "opendiscord:close":ODHelpMenuCommandComponent,
- "opendiscord:delete":ODHelpMenuCommandComponent,
- "opendiscord:reopen":ODHelpMenuCommandComponent
-}
-
-/**## ODHelpMenuCategory_DefaultTicketBasic `default_class`
- * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`!
- */
-export class ODHelpMenuCategory_DefaultTicketBasic extends ODHelpMenuCategory {
- get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId]
- get(id:ODValidId): ODHelpMenuComponent|null
-
- get(id:ODValidId): ODHelpMenuComponent|null {
- return super.get(id)
- }
-
- remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId]
- remove(id:ODValidId): ODHelpMenuComponent|null
-
- remove(id:ODValidId): ODHelpMenuComponent|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketBasic): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
-
-/**## ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced `type`
- * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketAdvanced` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced {
- "opendiscord:pin":ODHelpMenuCommandComponent,
- "opendiscord:unpin":ODHelpMenuCommandComponent,
- "opendiscord:move":ODHelpMenuCommandComponent,
- "opendiscord:rename":ODHelpMenuCommandComponent
-}
-
-/**## ODHelpMenuCategory_DefaultTicketAdvanced `default_class`
- * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`!
- */
-export class ODHelpMenuCategory_DefaultTicketAdvanced extends ODHelpMenuCategory {
- get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId]
- get(id:ODValidId): ODHelpMenuComponent|null
-
- get(id:ODValidId): ODHelpMenuComponent|null {
- return super.get(id)
- }
-
- remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId]
- remove(id:ODValidId): ODHelpMenuComponent|null
-
- remove(id:ODValidId): ODHelpMenuComponent|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
-
-/**## ODHelpMenuManagerCategoryIds_DefaultTicketUser `type`
- * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketUser` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODHelpMenuManagerCategoryIds_DefaultTicketUser {
- "opendiscord:claim":ODHelpMenuCommandComponent,
- "opendiscord:unclaim":ODHelpMenuCommandComponent,
- "opendiscord:add":ODHelpMenuCommandComponent,
- "opendiscord:remove":ODHelpMenuCommandComponent,
- "opendiscord:transfer":ODHelpMenuCommandComponent,
-}
-
-/**## ODHelpMenuCategory_DefaultTicketUser `default_class`
- * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`!
- */
-export class ODHelpMenuCategory_DefaultTicketUser extends ODHelpMenuCategory {
- get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId]
- get(id:ODValidId): ODHelpMenuComponent|null
-
- get(id:ODValidId): ODHelpMenuComponent|null {
- return super.get(id)
- }
-
- remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId]
- remove(id:ODValidId): ODHelpMenuComponent|null
-
- remove(id:ODValidId): ODHelpMenuComponent|null {
- return super.remove(id)
- }
-
- exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketUser): boolean
- exists(id:ODValidId): boolean
-
- exists(id:ODValidId): boolean {
- return super.exists(id)
- }
-}
-
-/**## ODHelpMenuManagerCategoryIds_DefaultAdmin `type`
- * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultAdmin` class.
- * It's used to generate typescript declarations for this class.
- */
-export interface ODHelpMenuManagerCategoryIds_DefaultAdmin {
- "opendiscord:panel":ODHelpMenuCommandComponent,
- "opendiscord:blacklist-view":ODHelpMenuCommandComponent,
- "opendiscord:blacklist-add":ODHelpMenuCommandComponent,
- "opendiscord:blacklist-remove":ODHelpMenuCommandComponent,
- "opendiscord:blacklist-get":ODHelpMenuCommandComponent
-}
-
-/**## ODHelpMenuCategory_DefaultAdmin `default_class`
- * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
- * It doesn't add any extra features!
- *
- * This default class is made for the `opendiscord:admin` category in `opendiscord.helpmenu`!
- */
-export class ODHelpMenuCategory_DefaultAdmin extends ODHelpMenuCategory {
- get