Compare commits

...
32 Commits
Author SHA1 Message Date
Jasper a12f60136a Open Ticket v4.0.6
Open Ticket v4.0.6
2025-05-31 11:01:13 +02:00
DJj123dj 1d05d04bf2 Updated all versions to v4.0.6 2025-05-31 10:51:29 +02:00
DJj123dj ff6a9eefaf Update package.json 2025-05-31 10:43:04 +02:00
DJj123dj aa9004d7e2 Compare/diff persian language + translation improv 2025-05-31 10:42:18 +02:00
Jasper 7e1fe78a26 Merge pull request #172 from zhavis/development (Persian translation)
Create persian.json
2025-05-31 10:29:05 +02:00
DJj123dj 675571b8d8 Added recommended hostings to README.md
Want to advertise your hosting too? Contact us in our discord server.
2025-05-31 10:24:32 +02:00
DJj123dj 48f0d65fad Fixed slash cmd registration bug
This was caused by already registered commands of a different type than 'chatInput'.
2025-05-31 10:24:04 +02:00
zhavihosseini a54422b222 Create persian.json 2025-05-28 07:11:03 +03:30
Jasper b965a4f5a2 Open Ticket v4.0.5
Open Ticket v4.0.5
2025-05-03 21:09:55 +02:00
DJj123dj 0d8dd8cd17 Updated all versions to v4.0.5 2025-05-03 21:02:47 +02:00
DJj123dj 6ac432cadc Fix: Panels now require at least 1 option. 2025-05-03 20:59:22 +02:00
DJj123dj dec6c7598b Improv: Decreased QuickBuilder boilerplate params 2025-05-03 20:58:50 +02:00
DJj123dj 2de2e3cd9b Fixed option suffixes with ot-sqlite-database 2025-05-03 18:34:10 +02:00
Jasper 5d0776a9b9 Open Ticket v4.0.4
Open Ticket v4.0.4
2025-05-01 14:10:55 +02:00
Jasper 7bf843c851 Dev v4.0.4
Dev v4.0.4
2025-05-01 14:05:56 +02:00
DJj123dj 3e3ea9263f Updated all versions to v4.0.4 2025-05-01 14:05:06 +02:00
DJj123dj bb5c3e9c8d Support for HTML Transcripts v2.1 2025-05-01 13:56:38 +02:00
Jasper 94f32674cb Open Ticket v4.0.3
Open Ticket v4.0.3
2025-04-28 18:27:48 +02:00
DJj123dj e8eb52e00b #155 : Fixed reply on creation when disabled.
Fixed a bug that caused the bot to send a partial ephemeral message while "replyOnTicketCreation" was disabled.
2025-04-28 18:22:54 +02:00
DJj123dj 4efa165949 Updated all versions to v4.0.3 2025-04-27 18:21:56 +02:00
DJj123dj 4c3e4ef9a5 Fixed bug due to discord.js new components 2025-04-27 18:17:38 +02:00
Jasper 6355fb5562 Open Ticket v4.0.2
Open Ticket v4.0.2
2025-04-12 19:19:06 +02:00
DJj123dj 442c201994 Updated all version badges to v4.0.2 2025-04-12 19:02:57 +02:00
DJj123dj b61f9d4d5a Update README.md 2025-04-12 18:57:53 +02:00
DJj123dj 129053b9f5 Fixed autoclose hours showing the wrong number.
Fixed that the ticket message embed shows the wrong amount of hours when used manually with /autoclose enable
2025-04-08 22:06:22 +02:00
DJj123dj 35a0511b97 Merge branch 'dev' of https://github.com/open-discord-bots/open-ticket into dev 2025-04-08 22:01:38 +02:00
DJj123dj bae221056c Fixed #149 Tickets not changing categories 2025-04-08 22:01:36 +02:00
DJj123dj 9c6e4ccde4 Update checkerLoader.ts 2025-04-08 21:59:08 +02:00
Roppl3r ac6845b4d4 Fixed Issue #151 (Max length for option 'name' should be 45, currently set to 50)
Fixed config checker bug related to the name of a ticket option in a dropdown.
2025-04-08 21:58:03 +02:00
DJj123dj 75770c84b2 Update README.md preview images 2025-04-08 09:03:41 +02:00
DJj123dj 2281d78896 Implemented Vietnamese translations 2025-04-07 18:13:23 +02:00
ngocdiep2006 37cc3b794e Added Vietnamese translation
Create vietnamese.json
2025-04-07 18:07:59 +02:00
66 changed files with 1843 additions and 441 deletions
+16 -1
View File
@@ -2,7 +2,7 @@
<img src="https://apis.dj-dj.be/cdn/openticket/logo.png" alt="Open Ticket Logo" width="500px">
[![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3)
[![version](https://img.shields.io/badge/version-4.0.1-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.1)
[![version](https://img.shields.io/badge/version-4.0.6-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.6)
[![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj)
[![Open Ticket supports Pterodactyl Eggs!](https://img.shields.io/badge/pterodactyl-supported-10539F?style=flat-square&logo=pterodactyl)](.eggs/README.md)
@@ -20,6 +20,21 @@ 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.0.6.json`**](openticket-egg-v4.0.6.json)
- This egg will always use Open Ticket `v4.0.6`. Open Ticket updates will not have an effect on this egg.
[**`openticket-egg-v4.0.5.json`**](openticket-egg-v4.0.5.json)
- This egg will always use Open Ticket `v4.0.5`. Open Ticket updates will not have an effect on this egg.
[**`openticket-egg-v4.0.4.json`**](openticket-egg-v4.0.4.json)
- This egg will always use Open Ticket `v4.0.4`. Open Ticket updates will not have an effect on this egg.
[**`openticket-egg-v4.0.3.json`**](openticket-egg-v4.0.3.json)
- This egg will always use Open Ticket `v4.0.3`. Open Ticket updates will not have an effect on this egg.
[**`openticket-egg-v4.0.2.json`**](openticket-egg-v4.0.2.json)
- This egg will always use Open Ticket `v4.0.2`. Open Ticket updates will not have an effect on this egg.
[**`openticket-egg-v4.0.1.json`**](openticket-egg-v4.0.1.json)
- This egg will always use Open Ticket `v4.0.1`. Open Ticket updates will not have an effect on this egg.
+62
View File
@@ -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.0.2)",
"author": "support@dj-dj.be",
"description": "This is the official Pterodactyl egg for Open Ticket v4.0.2, 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.0.2)\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.0.2\"\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"
}
]
}
+62
View File
@@ -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.0.3)",
"author": "support@dj-dj.be",
"description": "This is the official Pterodactyl egg for Open Ticket v4.0.3, 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.0.3)\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.0.3\"\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"
}
]
}
+62
View File
@@ -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.0.4)",
"author": "support@dj-dj.be",
"description": "This is the official Pterodactyl egg for Open Ticket v4.0.4, 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.0.4)\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.0.4\"\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"
}
]
}
+62
View File
@@ -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.0.5)",
"author": "support@dj-dj.be",
"description": "This is the official Pterodactyl egg for Open Ticket v4.0.5, 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.0.5)\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.0.5\"\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"
}
]
}
+62
View File
@@ -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.0.6)",
"author": "support@dj-dj.be",
"description": "This is the official Pterodactyl egg for Open Ticket v4.0.6, 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.0.6)\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.0.6\"\r\n\r\nif [ \"$(ls -A \/mnt\/server)\" ]; then\r\n echo -e \"[OT INSTALLER] \/mnt\/server directory is not empty.\"\r\n if [ -d .git ]; then\r\n echo -e \"[OT INSTALLER] .git directory exists\"\r\n if [ -f .git\/config ]; then\r\n echo -e \"[OT INSTALLER] loading info from git config\"\r\n ORIGIN=$(git config --get remote.origin.url)\r\n else\r\n echo -e \"[OT INSTALLER] files found with no git config\"\r\n echo -e \"[OT INSTALLER] closing out without touching things to not break anything\"\r\n exit 10\r\n fi\r\n fi\r\n\r\n if [ \"${ORIGIN}\" == \"https:\/\/github.com\/open-discord-bots\/open-ticket.git\" ]; then\r\n echo \"pulling latest from github\"\r\n git pull\r\n fi\r\nelse\r\n echo -e \"[OT INSTALLER] \/mnt\/server is empty.\"\r\n echo -e \"[OT INSTALLER] cloning files into repo.\"\r\n if [ -z ${BRANCH} ]; then\r\n echo -e \"[OT INSTALLER] cloning default branch\"\r\n git clone https:\/\/github.com\/open-discord-bots\/open-ticket.git .\r\n else\r\n echo -e \"[OT INSTALLER] cloning ${BRANCH}'\"\r\n git clone --single-branch --branch ${BRANCH} https:\/\/github.com\/open-discord-bots\/open-ticket.git .\r\n fi\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing Open Ticket node.js packages.\"\r\nif [ -f \/mnt\/server\/package.json ]; then\r\n \/usr\/local\/bin\/npm install --omit=dev\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing custom node.js packages.\"\r\nif [[ ! -z ${NODE_PACKAGES} ]]; then\r\n \/usr\/local\/bin\/npm install ${NODE_PACKAGES}\r\nfi\r\n\r\necho -e \"[OT INSTALLER] install complete!\"\r\nexit 0",
"container": "node:latest",
"entrypoint": "bash"
}
},
"variables": [
{
"name": "Additional Npm Packages",
"description": "Specify additional npm packages used by Open Ticket plugins. Use spaces to separate.",
"env_variable": "NODE_PACKAGES",
"default_value": "",
"user_viewable": false,
"user_editable": true,
"rules": "string|nullable",
"field_type": "text"
},
{
"name": "Startup Flags",
"description": "Start the bot with additional Open Ticket flags. Separate using spaces.\r\nA full reference list can be found in the documentation.",
"env_variable": "NODE_FLAGS",
"default_value": "",
"user_viewable": false,
"user_editable": true,
"rules": "string|nullable",
"field_type": "text"
},
{
"name": "Uninstall Npm Packages",
"description": "A list of npm packages to uninstall. Separate by spaces.",
"env_variable": "UNNODE_PACKAGES",
"default_value": "",
"user_viewable": false,
"user_editable": true,
"rules": "string|nullable",
"field_type": "text"
}
]
}
+1 -1
View File
@@ -1,7 +1,7 @@
# Contributing Guidelines
<img src="https://apis.dj-dj.be/cdn/openticket/logo.png" alt="Open Ticket Logo" width="500px">
[![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-4.0.1-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.1) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj)
[![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-4.0.6-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.6) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj)
These are the Contributing Guidelines of Open Ticket!<br>
Here you can find everything you need to know about contributing to Open Ticket.<br>
+12 -9
View File
@@ -1,7 +1,7 @@
# Security Policy
<img src="https://apis.dj-dj.be/cdn/openticket/logo.png" alt="Open Ticket Logo" width="500px">
[![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-4.0.1-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.1) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj)
[![discord](https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-4.0.4-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.4) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj)
This is the Security Policy of Open Ticket!<br>
Here you can find a list of all supported & deprecated versions of the bot.<br>
@@ -17,14 +17,17 @@ This list will be updated on every release.
- 🟧 Deprecated **(docs)**
- ❌ Fully Deprecated
| Version | Supported | Notes |
|------------|-----------|--------------------------------|
| 4.1.0 | 🟦 | |
| 4.0.1 | ✅ | |
| 4.0.0 | ✅ | |
| 3.5.9 | 🚧 | Supported until May 2025 (LTS) |
| 3.5.8 | 🟧 | Documentation Only |
| < 3.5.8 | ❌ | |
| Version | Supported | Notes |
|------------|-----------|------------------------------------------|
| 4.1.0 | 🟦 | |
| 4.0.6 | ✅ | |
| 4.0.5 | ✅ | |
| 4.0.4 | ✅ | Supported until July 2025 (LTS) |
| 4.0.3 | 🚧 | Transcripts v2.0 (Offline August 2025) |
| 4.0.2 | 🟧 | Documentation Only (discord.js bug) |
| 4.0.1 | 🟧 | Documentation Only |
| 4.0.0 | 🟧 | Documentation Only |
| < 4.0.0 | ❌ | |
### 🕷️ Reporting Vulnerabilities
You can report vulnerabilities, errors & bugs using one of the following methods:
+93 -80
View File
@@ -8,7 +8,7 @@
<br>Powered By<br>
<img src="https://apis.dj-dj.be/cdn/opendiscord/logo.png" alt="Open Ticket" width="170px"><br>
<a href="https://discord.com/invite/26vT9wt3n3"><img alt="Discord Invite Link" src="https://img.shields.io/badge/discord-support%20server-5865F2.svg?style=flat-square&logo=discord"></img></a>
<a href="https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.1"><img alt="Open Ticket Version" src="https://img.shields.io/badge/version-4.0.1-brightgreen.svg?style=flat-square"></img></a>
<a href="https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.6"><img alt="Open Ticket Version" src="https://img.shields.io/badge/version-4.0.6-brightgreen.svg?style=flat-square"></img></a>
<a href="https://otdocs.dj-dj.be"><img alt="Open Ticket Documentation" src="https://img.shields.io/badge/discord.js-v14-CB3837.svg?style=flat-square&logo=npm"></img></a>
<a href="https://github.com/open-discord-bots/open-ticket/blob/main/LICENSE"><img alt="Open Ticket License" src="https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square"></img></a>
<a href="https://otdocs.dj-dj.be"><img alt="Open Ticket Stars" src="https://img.shields.io/github/stars/djj123dj/open-ticket?color=yellow&label=stars&logo=github&style=flat-square"></img></a>
@@ -20,7 +20,7 @@
<p align="center">
Open Ticket is the most advanced & customisable discord ticket bot that you will ever find! You can customise up to 300+ variables! This includes <code>Html Transcripts</code>, <code>Advanced Plugins</code>, <code>Custom Embeds</code>, <code>Questions/Modals</code>, <code>Stats</code> & more!
You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than <code>26 Languages</code>! If you need any help, feel free to join our <a href="https://discord.dj-dj.be">discord server</a>!
You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than <code>28 Languages</code>! If you need any help, feel free to join our <a href="https://discord.dj-dj.be">discord server</a>!
</p>
<p align="center"><b>⭐️ Help us grow by giving a star! ⭐️</b></p>
@@ -32,7 +32,7 @@ You're also able to customise every little aspect of the bot! From embeds to tra
- **📈 scalable** - Open Ticket is made to handle huge servers! (Already tested in **servers with 100k members**)
- **📄 HTML transcripts** - Make use of the most customisable, beautiful and easy-to-use HTML Transcripts!
- **✅ ticket actions** - Close, Reopen, Delete, Claim, Pin, Rename & Move all your tickets!
- **🇬🇧 translation** - Open Ticket has been translated in more than **26 languages** by our community!
- **🇬🇧 translation** - Open Ticket has been translated in more than **28 languages** by our community!
- **🎨 customisation** - Open Ticket has been created around customisation, everything can be customised!
- **🖥️ interactions** - The bot has full support for Buttons, Dropdowns, Slash Commands and Modals!
- **∞ unlimited** - Create an infinite amount of tickets & panels!
@@ -58,9 +58,9 @@ You're also able to customise every little aspect of the bot! From embeds to tra
- **😁 And so much more...**
> ### 📦 Resources
> Resources might not be accurate yet! *(because v4 is still in beta)*<br>
> Not all resources are accurate yet! We are working on this.<br>
> <a href="https://www.youtube.com/watch?v=2jK9kAf6ASU"><img src="https://apis.dj-dj.be/cdn/openticket/open-ticket-tutorial.png" alt="Open Ticket Tutorial" width="180px"></a>
> <a href="https://otdocs.dj-dj.be"><img src="https://apis.dj-dj.be/cdn/openticket/open-ticket-docs.png" alt="Open Ticket Docs" width="180px"></a>
> <a href="https://openticket.dj-dj.be/message.html?msg=The%20current%20tutorial%20is%20outdated,%20we%27re%20still%20working%20on%20a%20new%20one!"><img src="https://apis.dj-dj.be/cdn/openticket/open-ticket-docs.png" alt="Open Ticket Docs" width="180px"></a>
> <a href="https://github.com/open-discord-bots/plugins"><img src="https://apis.dj-dj.be/cdn/openticket/open-ticket-plugins.png" alt="Open Ticket Plugins" width="180px"></a>
### ❤️ Sponsors
@@ -68,12 +68,10 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat
<table>
<tr>
<td><img src="https://github.com/roppl3r.png" alt="Profile Picture" width="80px"></td>
<td><img src="https://github.com/BENZORICH.png" alt="Profile Picture" width="80px"></td>
<td><img src="https://github.com/guillee3.png" alt="Profile Picture" width="100px"></td>
</tr>
<tr>
<th><a href="https://github.com/roppl3r">roppl3r</a></th>
<th><a href="https://github.com/BENZORICH">BENZORICH</a></th>
<td align="center"><a href="https://github.com/guillee3"><b>guillee3</b></a></td>
</tr>
</table>
@@ -82,6 +80,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat
<img src="https://github.com/SpyEye2.png" alt="SpyEye" width="40px">
<img src="https://github.com/mods-hd.png" alt="Mods HD" width="40px">
<img src="https://github.com/DOSEV5.png" alt="DOSEV5" width="40px">
<img src="https://github.com/BENZORICH.png" alt="BENZORICH" width="40px">
</a>
### ⏱️ Quick Setup
@@ -94,12 +93,92 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat
> - Fix these errors and restart the bot.
> 6. Enjoy using Open Ticket!
> ### [📔 Visit Documentation](https://otdocs.dj-dj.be)
>
> ### 🖥️ Recommended Hostings
> - [⭐ **Peakhosting.nl**](https://peakhosting.nl/) - Official support for Open Ticket pterodactyl eggs.
> - **Any Pterodactyl-Based Panel** - Easy installation & configuration.
> - **A Virtual Private Server (VPS)** - Extra customisation & more stability. Recommended for large servers.
>
> *❤️ Want to display your hosting here? Contact us in our [Discord server](https://discord.dj-dj.be)!*
## 📸 Preview
<img alt="Ticket Message" width="350px" src="https://apis.dj-dj.be/cdn/openticket/preview-v4/ticket.png">
<img alt="Ticket Stats Message" width="350px" src="https://apis.dj-dj.be/cdn/openticket/preview-v4/stats.png">
<img alt="Example Panel 1" width="350px" src="https://apis.dj-dj.be/cdn/openticket/preview-v4/panel-1.png">
<img alt="Example Panel 2" width="350px" src="https://apis.dj-dj.be/cdn/openticket/preview-v4/panel-2.png">
<img alt="An example of a panel." src="https://apis.dj-dj.be/cdn/openticket/preview-v4/panel-examples.png">
<img alt="An example of a ticket message." src="https://apis.dj-dj.be/cdn/openticket/preview-v4/ticket-example.png">
<img alt="Examples of built-in commands." src="https://apis.dj-dj.be/cdn/openticket/preview-v4/command-examples.png">
## 🛠️ Contributors
### 🖥️ Team & Contributors
A list of people that contributed or provided the most support for Open Ticket.
<table>
<tr>
<td align="center"><img src="https://github.com/DJj123dj.png" alt="Profile Picture" width="80px"></td>
<td align="center"><img src="https://github.com/smetsliam.png" alt="Profile Picture" width="80px"></td>
<td align="center"><img src="https://github.com/FrankVissers.png" alt="Profile Picture" width="80px"></td>
<td align="center"><img src="https://github.com/Sank34.png" alt="Profile Picture" width="80px"></td>
<td align="center"><img src="https://github.com/Roppl3r.png" alt="Profile Picture" width="80px"></td>
</tr>
<tr>
<th><a href="https://github.com/DJj123dj">💻 DJj123dj</a></th>
<th><a href="https://github.com/smetsliam">💬 smetsliam</a></th>
<th><a href="https://github.com/FrankVissers">💬 Frank Vissers</a></th>
<th><a href="https://github.com/Sank34">💬 Sanke</a></th>
<th><a href="https://github.com/Roppl3r">🧩 Roppl3r</a></th>
</tr>
</table>
### 💬 Translators
Without our translators, it wouldn't be possible to translate Open Ticket in so many languages!
- 🟢 Available - 🤖 Made Using AI - 🔴 Unavailable/Outdated
|🔍 |Language |Maintainer (Github/Discord) |
|---|---------------------|----------------------------|
|🟢 |🇬🇧 English |djj123dj |
|🟢 |🇳🇱 Dutch |djj123dj |
|🟢 |🇩🇪 German |benzorich |
|🟢 |🇪🇸 Spanish |redactado & josuens |
|🟢 |🇵🇹 Portuguese |quiradon |
|🟢 |❓ Catalan |guillee3 |
|🟢 |🇨🇿 Czech |spyeye_ |
|🟢 |🇭🇺 Hungarian |kornel0706 |
|🟢 |🇷🇴 Romanian |sankedev |
|🟢 |🇺🇦 Ukrainian |anderskiy |
|🟢 |🇮🇩 Indonesian |erxg |
|🟢 |🇮🇹 Italian |fraden1mvp. |
|🟢 |🇩🇰 Danish |the_gamer |
|🟢 |🇹🇭 Thai |modshd |
|🟢 |🇹🇷 Turkish |palestinian |
|🟢 |🇫🇷 French |guillee.3 |
|🟢 |🇦🇪 Arabic |palestinian |
|🟢 |🇮🇳 Hindi |an_developer |
|🟢 |🇱🇹 Lithuanian |tsgindrius |
|🟢 |🇵🇱 Polish |danoglez |
|🟢 |🇳🇴 Norwegian |NoOneNook |
|🟢 |🇸🇪 Swedish |NoOneNook |
|🟢 |🇮🇷 Persian |dysashop & zhavis |
|🤖 |🇪🇪 Estonian |iamnotmega |
|🤖 |🇫🇮 Finnish |iamnotmega |
|🤖 |🇷🇺 Russian |NoOneNook |
|🤖 |🇱🇻 Latvian |NoOneNook |
|🤖 |🇻🇳 Vietnamese |ngocdiep2006 |
|🔴 |🇯🇵 Japanese |[⭐ Contribute!](.github/CONTRIBUTING.md)|
|🔴 |🇰🇷 Korean |[⭐ Contribute!](.github/CONTRIBUTING.md)|
|🔴 |🇨🇳 Simplified Chinese |[⭐ Contribute!](.github/CONTRIBUTING.md)|
|🔴 |🇨🇳 Traditional Chinese|[⭐ Contribute!](.github/CONTRIBUTING.md)|
|🔴 |🇸🇮 Slovenian |[⭐ Contribute!](.github/CONTRIBUTING.md)|
|🔴 |🇬🇷 Greek |[⭐ Contribute!](.github/CONTRIBUTING.md)|
|🔴 |❓ Kurdish |[⭐ Contribute!](.github/CONTRIBUTING.md)|
## ⭐️ Star History
Please give this repository a star if you like it.
This will help us grow and reach even more people!
<a href="https://star-history.com/#open-discord-bots/open-ticket&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=open-discord-bots/open-ticket&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=open-discord-bots/open-ticket&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=open-discord-bots/open-ticket&type=Date" />
</picture>
</a>
## 🧩 Plugins
**Download all plugins in our [Official Plugin Repository](https://github.com/open-discord-bots/plugins)!**<br>
@@ -153,76 +232,10 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat
- **💼 Management** - These plugins add features that help you manage your server.
- **🤖 Client** - These plugins add features affecting the discord client or bot itself.
## 🛠️ Contributors
### 🖥️ Team
This is the main team working on Open Ticket. Don't forget to check their profiles!
<table>
<tr>
<td><img src="https://github.com/DJj123dj.png" alt="Profile Picture" width="80px"></td>
<td><img src="https://github.com/Sank34.png" alt="Profile Picture" width="80px"></td>
<td><img src="https://github.com/smetsliam.png" alt="Profile Picture" width="80px"></td>
</tr>
<tr>
<th><a href="https://github.com/DJj123dj">💻 DJj123dj</a></th>
<th><a href="https://github.com/Sank34">💬 Sanke</a></th>
<th><a href="https://github.com/smetsliam">💬 DevBack</a></th>
</tr>
</table>
### 💬 Translators
|Language |Maintainer (discord name) |Status |
|---------------------|--------------------------|-----------------------------|
|🇬🇧 English |djj123dj |🟢 Up To Date |
|🇳🇱 Dutch |djj123dj |🟢 Up To Date |
|🇩🇪 German |benzorich |🟢 Up To Date |
|🇪🇸 Spanish |redactado & josuens |🟢 Up To Date |
|🇵🇹 Portuguese |quiradon |🟢 Up To Date |
|❓ Catalan |guillee3 |🟢 Up To Date |
|🇨🇿 Czech |spyeye_ |🟢 Up To Date |
|🇭🇺 Hungarian |kornel0706 |🟢 Up To Date |
|🇷🇴 Romanian |sankedev |🟢 Up To Date |
|🇺🇦 Ukrainian |anderskiy |🟢 Up To Date |
|🇮🇩 Indonesian |erxg |🟢 Up To Date |
|🇮🇹 Italian |fraden1mvp. |🟢 Up To Date |
|🇩🇰 Danish |the_gamer |🟢 Up To Date |
|🇹🇭 Thai |modshd |🟢 Up To Date |
|🇹🇷 Turkish |palestinian |🟢 Up To Date |
|🇫🇷 French |guillee.3 |🟢 Up To Date |
|🇦🇪 Arabic |palestinian |🟢 Up To Date |
|🇮🇳 Hindi |an_developer |🟢 Up To Date |
|🇱🇹 Lithuanian |tsgindrius |🟢 Up To Date |
|🇵🇱 Polish |danoglez |🟢 Up To Date |
|🇳🇴 Norwegian |NoOneNook |🟢 Up To Date |
|🇸🇪 Swedish |NoOneNook |🟢 Up To Date |
|🇪🇪 Estonian |iamnotmega |🔵 Up To Date (AI) |
|🇫🇮 Finnish |iamnotmega |🔵 Up To Date (AI) |
|🇷🇺 Russian |NoOneNook |🔵 Up To Date (AI) |
|🇱🇻 Latvian |NoOneNook |🔵 Up To Date (AI) |
|🇯🇵 Japanese |/ |🔴 Missing |
|🇰🇷 Korean |/ |🔴 Missing |
|🇨🇳 Simplified Chinese |/ |🔴 Missing |
|🇨🇳 Traditional Chinese|/ |🔴 Missing |
|🇻🇳 Vietnamese |/ |🔴 Missing |
|🇸🇮 Slovenian |/ |🔴 Missing |
|🇬🇷 Greek |/ |🔴 Missing |
|❓ Kurdish |/ |🔴 Missing |
|❓ Persian |/ |🔴 Missing |
## ⭐️ Star History
Please help us grow by giving a star! It would help us a lot!
<a href="https://star-history.com/#open-discord-bots/open-ticket&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=open-discord-bots/open-ticket&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=open-discord-bots/open-ticket&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=open-discord-bots/open-ticket&type=Date" />
</picture>
</a>
---
<img src="https://apis.dj-dj.be/cdn/openticket/logo.png" alt="Open Ticket Logo" width="170px">
**README.md**<br>
[changelog](https://otgithub.dj-dj.be/releases) - [documentation](https://otdocs.dj-dj.be) - [tutorial](https://www.youtube.com/watch?v=2jK9kAf6ASU) - [website](https://openticket.dj-dj.be) - [discord](https://discord.dj-dj.be) - [license](./LICENSE.md)<br>
[changelog](https://otgithub.dj-dj.be/releases) - [documentation](https://otdocs.dj-dj.be) - [tutorial](https://www.youtube.com/watch?v=2jK9kAf6ASU) - [website](https://openticket.dj-dj.be) - [discord server](https://discord.dj-dj.be) - [license](./LICENSE.md)<br>
© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms) - [Privacy Policy](https://www.dj-dj.be/privacy) - [Support Us](https://github.com/sponsors/DJj123dj)
+1 -1
View File
@@ -2,7 +2,7 @@
"_INFO":{
"support":"https://otdocs.dj-dj.be",
"discord":"https://discord.dj-dj.be",
"version":"open-ticket-v4.0.1"
"version":"open-ticket-v4.0.6"
},
"token":"your bot token here! (or leave empty when using 'tokenFromENV')",
+1 -1
View File
@@ -17,7 +17,7 @@
"image":"https://www.example.com/image.png (or leave empty)",
"thumbnail":"https://www.example.com/image.png (or leave empty)",
"footer":"Open Ticket v4.0.1 (or leave empty)",
"footer":"Open Ticket v4.0.6 (or leave empty)",
"fields":[
{"name":"field name","value":"field value","inline":false}
],
+1 -1
View File
@@ -49,7 +49,7 @@
},
"favicon":{
"enableCustomFavicon":false,
"imageUrl":"https://transcripts.dj-dj.be/favicon.png"
"imageUrl":"https://t.dj-dj.be/favicon.png"
}
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ process.argv.push(...flags)
██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║
╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║
╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝
v4.0.1 - Made by DJj123dj & Contributors
v4.0.6 - Made by DJj123dj & Contributors
Discord: https://discord.dj-dj.be
Docs: https://otdocs.dj-dj.be
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION": {
"otversion": "v4.0.1",
"otversion": "v4.0.6",
"translators": ["palestinian"],
"lastedited": "06/12/2024",
"language": "Arabic",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["guillee3"],
"lastedited":"21/08/2024",
"language":"Catalan",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["DJj123dj"],
"lastedited":"21/08/2024",
"language":"Custom",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["spyeye_"],
"lastedited":"21/08/2024",
"language":"Czech",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["the_gamer"],
"lastedited":"26/09/2024",
"language":"Danish",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["DJj123dj"],
"lastedited":"21/08/2024",
"language":"Dutch",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["DJj123dj"],
"lastedited":"21/08/2024",
"language":"English",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["iamnotmega","ChatGPT"],
"lastedited":"21/10/2024",
"language":"Estonian",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["iamnotmega","ChatGPT"],
"lastedited":"21/10/2024",
"language":"Finnish",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["guillee3"],
"lastedited":"04/12/2024",
"language":"French",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["benzorich"],
"lastedited":"06/10/2024",
"language":"German",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["an_developer"],
"lastedited":"14/12/2024",
"language":"Hindi",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["Kornel0706"],
"lastedited":"22/08/2024",
"language":"Hungarian",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["erxg"],
"lastedited":"25/08/2024",
"language":"Indonesian",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["fraden1mvp."],
"lastedited":"08/10/2024",
"language":"Italian",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION": {
"otversion": "v4.0.1",
"otversion": "v4.0.6",
"translators": ["NoOneNook"],
"lastedited": "25/03/2025",
"language": "Latvian",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["TsgIndrius"],
"lastedited":"26/01/2025",
"language":"Lithuanian",
+126 -126
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION": {
"otversion": "v4.0.1",
"otversion": "v4.0.6",
"translators": ["NoOneNook"],
"lastedited": "25/03/2025",
"language": "Norwegian",
@@ -92,138 +92,138 @@
"dropdownOption": "Et panel med nedtrekksmeny aktivert kan kun inneholde alternativer av typen 'sak'!"
}
},
"actions": {
"buttons": {
"create": "Opprett Sak",
"close": "Lukk Sak",
"delete": "Slett Sak",
"reopen": "Gjenåpne Sak",
"claim": "Ta Sak",
"unclaim": "Frigi Sak",
"pin": "Fest Sak",
"unpin": "Løsne Sak",
"clear": "Slett Saker",
"helpSwitchSlash": "Vis Skråstrekskommandoer",
"helpSwitchText": "Vis Tekstkommandoer",
"helpPage": "Side {0}",
"withReason": "Med Årsak",
"withoutTranscript": "Uten Utskrift"
},
"titles": {
"created": "Sak Opprettet",
"close": "Sak Lukket",
"delete": "Sak Slettet",
"reopen": "Sak Gjenåpnet",
"claim": "Sak Tatt",
"unclaim": "Sak Frigitt",
"pin": "Sak Festet",
"unpin": "Sak Løsnet",
"rename": "Sak Omdøpt",
"move": "Sak Flyttet",
"add": "Bruker Lagt Til Sak",
"remove": "Bruker Fjernet Fra Sak",
"actions": {
"buttons": {
"create": "Opprett Sak",
"close": "Lukk Sak",
"delete": "Slett Sak",
"reopen": "Gjenåpne Sak",
"claim": "Ta Sak",
"unclaim": "Frigi Sak",
"pin": "Fest Sak",
"unpin": "Løsne Sak",
"clear": "Slett Saker",
"helpSwitchSlash": "Vis Skråstrekskommandoer",
"helpSwitchText": "Vis Tekstkommandoer",
"helpPage": "Side {0}",
"withReason": "Med Årsak",
"withoutTranscript": "Uten Utskrift"
},
"titles": {
"created": "Sak Opprettet",
"close": "Sak Lukket",
"delete": "Sak Slettet",
"reopen": "Sak Gjenåpnet",
"claim": "Sak Tatt",
"unclaim": "Sak Frigitt",
"pin": "Sak Festet",
"unpin": "Sak Løsnet",
"rename": "Sak Omdøpt",
"move": "Sak Flyttet",
"add": "Bruker Lagt Til Sak",
"remove": "Bruker Fjernet Fra Sak",
"help": "Tilgjengelige Kommandoer",
"statsReset": "Tilbakestill Statistikk",
"blacklistAdd": "Bruker Svartelistet",
"blacklistRemove": "Bruker Fjernet Fra Svarteliste",
"blacklistGet": "Svartelistet Bruker",
"blacklistView": "Gjeldende Svarteliste",
"blacklistAddDm": "Lagt Til Svarteliste",
"blacklistRemoveDm": "Fjernet Fra Svarteliste",
"clear": "Saker Slettet",
"roles": "Roller Oppdatert",
"help": "Tilgjengelige Kommandoer",
"statsReset": "Tilbakestill Statistikk",
"blacklistAdd": "Bruker Svartelistet",
"blacklistRemove": "Bruker Fjernet Fra Svarteliste",
"blacklistGet": "Svartelistet Bruker",
"blacklistView": "Gjeldende Svarteliste",
"blacklistAddDm": "Lagt Til Svarteliste",
"blacklistRemoveDm": "Fjernet Fra Svarteliste",
"clear": "Saker Slettet",
"roles": "Roller Oppdatert",
"autoclose": "Sak Autolukket",
"autocloseEnabled": "Autolukking Aktivert",
"autocloseDisabled": "Autolukking Deaktivert",
"autodelete": "Sak Autoslettet",
"autodeleteEnabled": "Autosletting Aktivert",
"autodeleteDisabled": "Autosletting Deaktivert"
},
"descriptions": {
"create": "Din sak er blitt opprettet. Klikk på knappen nedenfor for å få tilgang til den!",
"close": "Saken er blitt lukket vellykket!",
"delete": "Saken er blitt slettet vellykket!",
"reopen": "Saken er blitt gjenåpnet vellykket!",
"claim": "Saken er blitt tatt vellykket!",
"unclaim": "Saken er blitt frigitt vellykket!",
"pin": "Saken er blitt festet vellykket!",
"unpin": "Saken er blitt løsnet vellykket!",
"rename": "Saken er blitt omdøpt til {0} vellykket!",
"move": "Saken er blitt flyttet til {0} vellykket!",
"add": "{0} er blitt lagt til saken vellykket!",
"remove": "{0} er blitt fjernet fra saken vellykket!",
"autoclose": "Sak Autolukket",
"autocloseEnabled": "Autolukking Aktivert",
"autocloseDisabled": "Autolukking Deaktivert",
"autodelete": "Sak Autoslettet",
"autodeleteEnabled": "Autosletting Aktivert",
"autodeleteDisabled": "Autosletting Deaktivert"
},
"descriptions": {
"create": "Din sak er blitt opprettet. Klikk på knappen nedenfor for å få tilgang til den!",
"close": "Saken er blitt lukket vellykket!",
"delete": "Saken er blitt slettet vellykket!",
"reopen": "Saken er blitt gjenåpnet vellykket!",
"claim": "Saken er blitt tatt vellykket!",
"unclaim": "Saken er blitt frigitt vellykket!",
"pin": "Saken er blitt festet vellykket!",
"unpin": "Saken er blitt løsnet vellykket!",
"rename": "Saken er blitt omdøpt til {0} vellykket!",
"move": "Saken er blitt flyttet til {0} vellykket!",
"add": "{0} er blitt lagt til saken vellykket!",
"remove": "{0} er blitt fjernet fra saken vellykket!",
"helpExplanation": "`<navn>` => påkrevd parameter\n`[navn]` => valgfri parameter",
"statsReset": "Botens statistikk er blitt tilbakestilt vellykket!",
"statsError": "Kan ikke vise saksstatistikk!\n{0} er ikke en sak!",
"blacklistAdd": "{0} er blitt svartelistet vellykket!",
"blacklistRemove": "{0} er blitt fjernet fra svartelisten vellykket!",
"blacklistGetSuccess": "{0} er for øyeblikket svartelistet!",
"blacklistGetEmpty": "{0} er for øyeblikket ikke svartelistet!",
"blacklistViewEmpty": "Ingen er svartelistet ennå!",
"blacklistViewTip": "Bruk \"/blacklist add\" for å svarteliste en bruker!",
"clearVerify": "Er du sikker på at du vil slette flere saker?\nDenne handlingen kan ikke angres!",
"clearReady": "{0} saker er blitt slettet vellykket!",
"rolesEmpty": "Ingen roller er blitt oppdatert!",
"helpExplanation": "`<navn>` => påkrevd parameter\n`[navn]` => valgfri parameter",
"statsReset": "Botens statistikk er blitt tilbakestilt vellykket!",
"statsError": "Kan ikke vise saksstatistikk!\n{0} er ikke en sak!",
"blacklistAdd": "{0} er blitt svartelistet vellykket!",
"blacklistRemove": "{0} er blitt fjernet fra svartelisten vellykket!",
"blacklistGetSuccess": "{0} er for øyeblikket svartelistet!",
"blacklistGetEmpty": "{0} er for øyeblikket ikke svartelistet!",
"blacklistViewEmpty": "Ingen er svartelistet ennå!",
"blacklistViewTip": "Bruk \"/blacklist add\" for å svarteliste en bruker!",
"clearVerify": "Er du sikker på at du vil slette flere saker?\nDenne handlingen kan ikke angres!",
"clearReady": "{0} saker er blitt slettet vellykket!",
"rolesEmpty": "Ingen roller er blitt oppdatert!",
"autocloseLeave": "Denne saken er blitt autolukket fordi oppretteren forlot serveren!",
"autocloseTimeout": "Denne saken er blitt autolukket fordi den har vært inaktiv i mer enn `{0}t`!",
"autodeleteLeave": "Denne saken er blitt autoslettet fordi oppretteren forlot serveren!",
"autodeleteTimeout": "Denne saken er blitt autoslettet fordi den har vært inaktiv i mer enn `{0} dager`!",
"autocloseEnabled": "Autolukking er blitt aktivert i denne saken!\nDen vil bli lukket når den er inaktiv i mer enn `{0}t`!",
"autocloseDisabled": "Autolukking er blitt deaktivert i denne saken!\nDen vil ikke lenger bli lukket automatisk!",
"autodeleteEnabled": "Autosletting er blitt aktivert i denne saken!\nDen vil bli slettet når den er inaktiv i mer enn `{0} dager`!",
"autodeleteDisabled": "Autosletting er blitt deaktivert i denne saken!\nDen vil ikke lenger bli slettet automatisk!",
"autocloseLeave": "Denne saken er blitt autolukket fordi oppretteren forlot serveren!",
"autocloseTimeout": "Denne saken er blitt autolukket fordi den har vært inaktiv i mer enn `{0}t`!",
"autodeleteLeave": "Denne saken er blitt autoslettet fordi oppretteren forlot serveren!",
"autodeleteTimeout": "Denne saken er blitt autoslettet fordi den har vært inaktiv i mer enn `{0} dager`!",
"autocloseEnabled": "Autolukking er blitt aktivert i denne saken!\nDen vil bli lukket når den er inaktiv i mer enn `{0}t`!",
"autocloseDisabled": "Autolukking er blitt deaktivert i denne saken!\nDen vil ikke lenger bli lukket automatisk!",
"autodeleteEnabled": "Autosletting er blitt aktivert i denne saken!\nDen vil bli slettet når den er inaktiv i mer enn `{0} dager`!",
"autodeleteDisabled": "Autosletting er blitt deaktivert i denne saken!\nDen vil ikke lenger bli slettet automatisk!",
"ticketMessageLimit": "Du kan kun opprette {0} sak(er) om gangen!",
"ticketMessageAutoclose": "Denne saken vil bli autolukket når den er inaktiv i {0}t!",
"ticketMessageAutodelete": "Denne saken vil bli autoslettet når den er inaktiv i {0} dager!",
"panelReady": "Du finner panelet nedenfor!\nDenne meldingen kan nå slettes!"
},
"modal": {
"closePlaceholder": "Hvorfor lukket du denne saken?",
"deletePlaceholder": "Hvorfor slettet du denne saken?",
"reopenPlaceholder": "Hvorfor gjenåpnet du denne saken?",
"claimPlaceholder": "Hvorfor tok du denne saken?",
"unclaimPlaceholder": "Hvorfor frigjorde du denne saken?",
"pinPlaceholder": "Hvorfor festet du denne saken?",
"unpinPlaceholder": "Hvorfor løsnet du denne saken?"
},
"logs": {
"createLog": "En ny sak er blitt opprettet av {0}!",
"closeLog": "Denne saken er blitt lukket av {0}!",
"closeDm": "Din sak er blitt lukket på vår server!",
"deleteLog": "Denne saken er blitt slettet av {0}!",
"deleteDm": "Din sak er blitt slettet på vår server!",
"reopenLog": "Denne saken er blitt gjenåpnet av {0}!",
"reopenDm": "Din sak er blitt gjenåpnet på vår server!",
"claimLog": "Denne saken er blitt tatt av {0}!",
"claimDm": "Din sak er blitt tatt på vår server!",
"unclaimLog": "Denne saken er blitt frigitt av {0}!",
"unclaimDm": "Din sak er blitt frigitt på vår server!",
"pinLog": "Denne saken er blitt festet av {0}!",
"pinDm": "Din sak er blitt festet på vår server!",
"unpinLog": "Denne saken er blitt løsnet av {0}!",
"unpinDm": "Din sak er blitt løsnet på vår server!",
"renameLog": "Denne saken er blitt omdøpt til {0} av {1}!",
"renameDm": "Din sak er blitt omdøpt til {0} på vår server!",
"moveLog": "Denne saken er blitt flyttet til {0} av {1}!",
"moveDm": "Din sak er blitt flyttet til {0} på vår server!",
"addLog": "{0} er blitt lagt til denne saken av {1}!",
"addDm": "{0} er blitt lagt til din sak på vår server!",
"removeLog": "{0} er blitt fjernet fra denne saken av {1}!",
"removeDm": "{0} er blitt fjernet fra din sak på vår server!",
"ticketMessageLimit": "Du kan kun opprette {0} sak(er) om gangen!",
"ticketMessageAutoclose": "Denne saken vil bli autolukket når den er inaktiv i {0}t!",
"ticketMessageAutodelete": "Denne saken vil bli autoslettet når den er inaktiv i {0} dager!",
"panelReady": "Du finner panelet nedenfor!\nDenne meldingen kan nå slettes!"
},
"modal": {
"closePlaceholder": "Hvorfor lukket du denne saken?",
"deletePlaceholder": "Hvorfor slettet du denne saken?",
"reopenPlaceholder": "Hvorfor gjenåpnet du denne saken?",
"claimPlaceholder": "Hvorfor tok du denne saken?",
"unclaimPlaceholder": "Hvorfor frigjorde du denne saken?",
"pinPlaceholder": "Hvorfor festet du denne saken?",
"unpinPlaceholder": "Hvorfor løsnet du denne saken?"
},
"logs": {
"createLog": "En ny sak er blitt opprettet av {0}!",
"closeLog": "Denne saken er blitt lukket av {0}!",
"closeDm": "Din sak er blitt lukket på vår server!",
"deleteLog": "Denne saken er blitt slettet av {0}!",
"deleteDm": "Din sak er blitt slettet på vår server!",
"reopenLog": "Denne saken er blitt gjenåpnet av {0}!",
"reopenDm": "Din sak er blitt gjenåpnet på vår server!",
"claimLog": "Denne saken er blitt tatt av {0}!",
"claimDm": "Din sak er blitt tatt på vår server!",
"unclaimLog": "Denne saken er blitt frigitt av {0}!",
"unclaimDm": "Din sak er blitt frigitt på vår server!",
"pinLog": "Denne saken er blitt festet av {0}!",
"pinDm": "Din sak er blitt festet på vår server!",
"unpinLog": "Denne saken er blitt løsnet av {0}!",
"unpinDm": "Din sak er blitt løsnet på vår server!",
"renameLog": "Denne saken er blitt omdøpt til {0} av {1}!",
"renameDm": "Din sak er blitt omdøpt til {0} på vår server!",
"moveLog": "Denne saken er blitt flyttet til {0} av {1}!",
"moveDm": "Din sak er blitt flyttet til {0} på vår server!",
"addLog": "{0} er blitt lagt til denne saken av {1}!",
"addDm": "{0} er blitt lagt til din sak på vår server!",
"removeLog": "{0} er blitt fjernet fra denne saken av {1}!",
"removeDm": "{0} er blitt fjernet fra din sak på vår server!",
"blacklistAddLog": "{0} er blitt svartelistet av {1}!",
"blacklistRemoveLog": "{0} er blitt fjernet fra svartelisten av {1}!",
"blacklistAddDm": "Du er blitt svartelistet på vår server!\nFra nå av kan du ikke opprette en sak!",
"blacklistRemoveDm": "Du er blitt fjernet fra svartelisten på vår server!\nNå kan du opprette saker igjen!",
"clearLog": "{0} saker er blitt slettet av {1}!"
"blacklistAddLog": "{0} er blitt svartelistet av {1}!",
"blacklistRemoveLog": "{0} er blitt fjernet fra svartelisten av {1}!",
"blacklistAddDm": "Du er blitt svartelistet på vår server!\nFra nå av kan du ikke opprette en sak!",
"blacklistRemoveDm": "Du er blitt fjernet fra svartelisten på vår server!\nNå kan du opprette saker igjen!",
"clearLog": "{0} saker er blitt slettet av {1}!"
}
},
"transcripts": {
},
"transcripts": {
"success": {
"visit": "Besøk Utskrift",
"ready": "Utskrift Opprettet",
+478
View File
@@ -0,0 +1,478 @@
{
"_TRANSLATION":{
"otversion":"v4.0.6",
"translators":["dysashop","zhavis"],
"lastedited":"28/05/2025",
"language":"Persian",
"automated":false
},
"checker":{
"system":{
"typeError":"[خطا]",
"headerOpenTicket":"بازکردن تیکت",
"typeWarning":"[اخطار]",
"typeInfo":"[اطلاعات]",
"headerConfigChecker":"جستجوگر پیکربندی",
"headerDescription":"برای خطاها فایل پیکربندی ( کانفیگ ) خود را چک کنید",
"footerError":"ربات تا تمام مدت شروع نمی شود {0}'s ثابت هستند!",
"footerWarning":"توصیه میشه همه رو تعمیر کنید {0}'s قبل از شروع کردن!",
"footerSupport":"پشتیبانی: {0} - اسناد: {1}",
"compactInformation":"استفاده کنید {0} برای اطلاعات بیشتر!",
"dataPath":"path",
"dataDocs":"docs",
"dataMessages":"message"
},
"messages":{
"stringTooShort":"این رشته نمیتواند کوتاه تر از این باشد {0} شخصیت ها!",
"stringTooLong":"این رشته نمیتواند طولانی تر از این باشد {0} شخصیت ها!",
"stringLengthInvalid":"این رشته باید باشد {0} شخصیت های طولانی!",
"stringStartsWith":"این رشته باید با آن شروع شود {0}!",
"stringEndsWith":"این رشته باید به پایان برسد {0}!",
"stringContains":"این رشته باید حاوی باشد {0}!",
"stringChoices":"این رشته فقط می تواند یکی از مقادیر زیر باشد: {0}!",
"stringRegex":"این رشته اشتباه است!",
"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": "این عدد نمی‌تواند صفر باشد!",
"booleanTrue": "این مقدار بولین نمی‌تواند درست (true) باشد!",
"booleanFalse": "این مقدار بولین نمی‌تواند نادرست (false) باشد!",
"arrayEmptyDisabled": "این آرایه نمی‌تواند خالی باشد!",
"arrayEmptyRequired": "این آرایه باید خالی باشد!",
"arrayTooShort": "طول این آرایه باید حداقل {0} باشد!",
"arrayTooLong": "طول این آرایه باید حداکثر {0} باشد!",
"arrayLengthInvalid": "طول این آرایه باید دقیقاً {0} باشد!",
"arrayInvalidTypes": "این آرایه فقط می‌تواند شامل انواع زیر باشد: {0}!",
"arrayDouble": "این آرایه نمی‌تواند مقادیر تکراری داشته باشد!",
"discordInvalidId": "این شناسه دیسکورد {0} نامعتبر است!",
"discordInvalidIdOptions": "این شناسه دیسکورد {0} نامعتبر است! می‌توانید از یکی از این موارد استفاده کنید: {1}!",
"discordInvalidToken": "این توکن دیسکورد از نظر ساختاری نامعتبر است!",
"colorInvalid": "این کد رنگ هگزادسیمال نامعتبر است!",
"emojiTooShort": "این رشته باید حداقل {0} ایموجی داشته باشد!",
"emojiTooLong": "این رشته باید حداکثر {0} ایموجی داشته باشد!",
"emojiCustom": "این ایموجی نمی‌تواند یک ایموجی سفارشی دیسکورد باشد!",
"emojiInvalid": "این ایموجی نامعتبر است!",
"urlInvalid": "این آدرس URL نامعتبر است!",
"urlInvalidHttp": "این آدرس URL فقط می‌تواند از پروتکل https:// استفاده کند!",
"urlInvalidProtocol": "این آدرس URL فقط می‌تواند از پروتکل‌های http:// و https:// استفاده کند!",
"urlInvalidHostname": "این آدرس URL دارای نام میزبان غیرمجازی است!",
"urlInvalidExtension": "این آدرس URL دارای پسوند نامعتبر است! یکی از موارد زیر را انتخاب کنید: {0}!",
"urlInvalidPath": "این آدرس URL دارای مسیر نامعتبر است!",
"idNotUnique": "این شناسه یکتا نیست، لطفاً از شناسه دیگری استفاده کنید!",
"idNonExistent": "شناسه {0} وجود ندارد!",
"invalidType": "این ویژگی باید از نوع {0} باشد!",
"propertyMissing": "ویژگی {0} در این شیء وجود ندارد!",
"propertyOptional": "ویژگی {0} در این شیء اختیاری است!",
"objectDisabled": "این شیء غیرفعال است، آن را با استفاده از {0} فعال کنید!",
"nullInvalid": "این ویژگی نمی‌تواند null باشد!",
"switchInvalidType": "این باید یکی از انواع زیر باشد: {0}!",
"objectSwitchInvalid": "این شیء باید یکی از انواع زیر باشد: {0}!",
"invalidLanguage": "این زبان نامعتبر است!",
"invalidButton": "این دکمه باید حداقل شامل یک {0} یا {1} باشد!",
"unusedOption": "گزینه {0} در هیچ جایی استفاده نشده است!",
"unusedQuestion": "سوال {0} در هیچ جایی استفاده نشده است!",
"dropdownOption": "پنلی که منوی کشویی آن فعال است، فقط می‌تواند شامل گزینه‌هایی از نوع 'تیکت' باشد!"
}
},
"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": "تیکت‌ها پاکسازی شدند",
"roles": "نقش‌ها به‌روزرسانی شدند",
"autoclose": "تیکت به‌صورت خودکار بسته شد",
"autocloseEnabled": "بسته شدن خودکار فعال شد",
"autocloseDisabled": "بسته شدن خودکار غیرفعال شد",
"autodelete": "تیکت به‌صورت خودکار حذف شد",
"autodeleteEnabled": "حذف خودکار فعال شد",
"autodeleteDisabled": "حذف خودکار غیرفعال شد"
},
"descriptions":{
"create": "تیکت شما با موفقیت ایجاد شد. برای دسترسی به آن، روی دکمه زیر کلیک کنید!",
"close": "تیکت با موفقیت بسته شد!",
"delete": "تیکت با موفقیت حذف شد!",
"reopen": "تیکت با موفقیت دوباره باز شد!",
"claim": "تیکت با موفقیت به شما اختصاص یافت!",
"unclaim": "تیکت با موفقیت از حالت اختصاص‌یافته خارج شد!",
"pin": "تیکت با موفقیت پین شد!",
"unpin": "تیکت با موفقیت از حالت پین خارج شد!",
"rename": "نام تیکت با موفقیت به {0} تغییر یافت!",
"move": "تیکت با موفقیت به {0} منتقل شد!",
"add": "کاربر {0} با موفقیت به تیکت اضافه شد!",
"remove": "کاربر {0} با موفقیت از تیکت حذف شد!",
"helpExplanation": "`<name>`: پارامتر اجباری\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} ساعت غیرفعال بوده است!",
"autodeleteLeave": "این تیکت به‌طور خودکار حذف شد زیرا ایجادکننده آن سرور را ترک کرده است!",
"autodeleteTimeout": "این تیکت به‌طور خودکار حذف شد زیرا بیش از {0} روز غیرفعال بوده است!",
"autocloseEnabled": "قابلیت بسته شدن خودکار برای این تیکت فعال شد!\nتیکت پس از {0} ساعت غیرفعال بودن بسته خواهد شد!",
"autocloseDisabled": "قابلیت بسته شدن خودکار برای این تیکت غیرفعال شد!\nتیکت دیگر به‌صورت خودکار بسته نخواهد شد!",
"autodeleteEnabled": "قابلیت حذف خودکار برای این تیکت فعال شد!\nتیکت پس از {0} روز غیرفعال بودن حذف خواهد شد!",
"autodeleteDisabled": "قابلیت حذف خودکار برای این تیکت غیرفعال شد!\nتیکت دیگر به‌صورت خودکار حذف نخواهد شد!",
"ticketMessageLimit": "شما تنها می‌توانید همزمان {0} تیکت ایجاد کنید!",
"ticketMessageAutoclose": "این تیکت پس از {0} ساعت غیرفعال بودن به‌صورت خودکار بسته خواهد شد!",
"ticketMessageAutodelete": "این تیکت پس از {0} روز غیرفعال بودن به‌صورت خودکار حذف خواهد شد!",
"panelReady": "پنل در زیر قابل مشاهده است!\nاکنون می‌توانید این پیام را حذف کنید!"
},
"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} حذف شدند!"
}
},
"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این تیکت تا زمانی که یکی از این دکمه‌ها را کلیک نکنید حذف نخواهد شد."
}
},
"errors":{
"titles":{
"internalError": "خطای داخلی",
"optionMissing": "گزینه دستور غایب است",
"optionInvalid": "گزینه دستور نامعتبر است",
"unknownCommand": "دستور ناشناخته",
"noPermissions": "بدون مجوز",
"unknownTicket": "تیکت ناشناخته",
"deprecatedTicket": "تیکت منسوخ‌شده",
"unknownOption": "گزینه ناشناخته",
"unknownPanel": "پنل ناشناخته",
"notInGuild": "خارج از سرور",
"channelRename": "عدم امکان تغییر نام کانال",
"busy": "تیکت مشغول است"
},
"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": "به دلیل محدودیت‌های نرخ دیسکورد، ربات در حال حاضر نمی‌تواند نام کانال را تغییر دهد. اگر ربات ری‌استارت نشود، نام کانال ظرف 10 دقیقه به‌طور خودکار تغییر خواهد کرد.",
"channelRenameSource": "منبع این خطا: {0}",
"busy": "امکان استفاده از این {0} وجود ندارد!\nتیکت در حال پردازش توسط ربات است.\n\nلطفاً چند ثانیه دیگر دوباره امتحان کنید!"
},
"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": "فیلتر",
"claimedBy": "اختصاص‌یافته به {0}",
"method": "روش",
"type": "نوع",
"blacklisted": "در لیست سیاه",
"panel": "پنل",
"command": "دستور",
"system": "سیستم",
"true": "درست",
"false": "نادرست",
"syntax": "نحوه نگارش",
"originalName": "نام اصلی",
"newName": "نام جدید",
"until": "تا",
"validOptions": "گزینه‌های معتبر",
"validPanels": "پنل‌های معتبر",
"autoclose": "بسته شدن خودکار",
"autodelete": "حذف خودکار",
"startupDate": "تاریخ راه‌اندازی",
"version": "نسخه",
"name": "نام",
"role": "نقش",
"status": "وضعیت",
"claimed": "اختصاص‌یافته",
"pinned": "پین‌شده",
"creationDate": "تاریخ ایجاد"
},
"lowercase":{
"text": "متن",
"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": "تعداد روزهایی که این تیکت باید غیرفعال باشد تا حذف شود."
},
"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": "حذف خودکار را در این تیکت فعال کنید."
},
"stats":{
"scopes":{
"global": "آمار کلی",
"system": "آمار سیستم",
"user": "آمار کاربر",
"ticket": "آمار تیکت",
"participants": "مشارکت‌کنندگان"
},
"properties":{
"ticketsCreated": "تیکت‌های ایجادشده",
"ticketsClosed": "تیکت‌های بسته‌شده",
"ticketsDeleted": "تیکت‌های حذف‌شده",
"ticketsReopened": "تیکت‌های دوباره بازشده",
"ticketsAutoclosed": "تیکت‌های بسته‌شده خودکار",
"ticketsClaimed": "تیکت‌های اختصاص‌ یافته",
"ticketsPinned": "تیکت‌های پین‌ شده",
"ticketsMoved": "تیکت‌های منتقل‌ شده",
"usersBlacklisted": "کاربران در لیست سیاه",
"transcriptsCreated": "رونوشت‌های ایجادشده"
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["DanoGlez"],
"lastedited":"28/01/2025",
"language":"Polish",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["quiradon"],
"lastedited":"20/08/2024",
"language":"Portuguese",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["SankeDev"],
"lastedited":"27/08/2024",
"language":"Romanian",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION": {
"otversion": "v4.0.1",
"otversion": "v4.0.6",
"translators": ["NoOneNook"],
"lastedited": "25/03/2025",
"language": "Russian",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["Redactado","Josuens"],
"lastedited":"22/08/2024",
"language":"Spanish",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION": {
"otversion": "v4.0.1",
"otversion": "v4.0.6",
"translators": ["NoOneNook"],
"lastedited": "25/03/2025",
"language": "Svenska",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["modshd"],
"lastedited":"13/11/2024",
"language":"Thai",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION": {
"otversion": "v4.0.1",
"otversion": "v4.0.6",
"translators": ["palestinian"],
"lastedited": "26/11/2024",
"language": "Turkish",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"_TRANSLATION":{
"otversion":"v4.0.1",
"otversion":"v4.0.6",
"translators":["Anderskiy"],
"lastedited":"31/08/2024",
"language":"Ukrainian",
+466
View File
@@ -0,0 +1,466 @@
{
"_TRANSLATION":{
"otversion":"v4.0.6",
"translators":["ngocdiep2006"],
"lastedited":"07/04/2025",
"language":"Vietnamese",
"automated":true
},
"checker":{
"system":{
"typeError":"[ERROR]",
"headerOpenTicket":"OPEN TICKET",
"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!",
"footerSupport":"SUPPORT: {0} - DOCS: {1}",
"compactInformation":"use {0} for more information!",
"dataPath":"path",
"dataDocs":"docs",
"dataMessages":"message"
},
"messages": {
"stringTooShort": "Chuỗi này không thể ngắn hơn {0} ký tự!",
"stringTooLong": "Chuỗi này không thể dài hơn {0} ký tự!",
"stringLengthInvalid": "Chuỗi này cần dài {0} ký tự!",
"stringStartsWith": "Chuỗi này cần bắt đầu bằng {0}!",
"stringEndsWith": "Chuỗi này cần kết thúc bằng {0}!",
"stringContains": "Chuỗi này cần chứa {0}!",
"stringChoices": "Chuỗi này chỉ có thể là một trong các giá trị sau: {0}!",
"stringRegex": "Chuỗi này không hợp lệ!",
"numberTooShort": "Số này không thể ngắn hơn {0} ký tự!",
"numberTooLong": "Số này không thể dài hơn {0} ký tự!",
"numberLengthInvalid": "Số này cần dài {0} ký tự!",
"numberTooSmall": "Số này cần ít nhất là {0}!",
"numberTooLarge": "Số này cần nhiều nhất là {0}!",
"numberNotEqual": "Số này cần là {0}!",
"numberStep": "Số này cần là bội số của {0}!",
"numberStepOffset": "Số này cần là bội số của {0} bắt đầu từ {1}!",
"numberStartsWith": "Số này cần bắt đầu bằng {0}!",
"numberEndsWith": "Số này cần kết thúc bằng {0}!",
"numberContains": "Số này cần chứa {0}!",
"numberChoices": "Số này chỉ có thể là một trong các giá trị sau: {0}!",
"numberFloat": "Số này không thể là số thập phân!",
"numberNegative": "Số này không thể là số âm!",
"numberPositive": "Số này không thể là số dương!",
"numberZero": "Số này không thể là số không!",
"booleanTrue": "Boolean này không thể là true!",
"booleanFalse": "Boolean này không thể là false!",
"arrayEmptyDisabled": "Mảng này không được phép rỗng!",
"arrayEmptyRequired": "Mảng này bắt buộc phải rỗng!",
"arrayTooShort": "Mảng này cần có độ dài ít nhất là {0}!",
"arrayTooLong": "Mảng này cần có độ dài nhiều nhất là {0}!",
"arrayLengthInvalid": "Mảng này cần có độ dài là {0}!",
"arrayInvalidTypes": "Mảng này chỉ có thể chứa các kiểu sau: {0}!",
"arrayDouble": "Mảng này không cho phép giá trị trùng lặp!",
"discordInvalidId": "Đây là id discord {0} không hợp lệ!",
"discordInvalidIdOptions": "Đây là id discord {0} không hợp lệ! Bạn cũng có thể sử dụng một trong những id sau: {1}!",
"discordInvalidToken": "Đây là token discord không hợp lệ (về mặt cú pháp)!",
"colorInvalid": "Đây là màu hex không hợp lệ!",
"emojiTooShort": "Chuỗi này cần có ít nhất {0} emoji!",
"emojiTooLong": "Chuỗi này cần có nhiều nhất {0} emoji!",
"emojiCustom": "Emoji này không thể là emoji discord tùy chỉnh!",
"emojiInvalid": "Đây là emoji không hợp lệ!",
"urlInvalid": "URL này không hợp lệ!",
"urlInvalidHttp": "URL này chỉ có thể sử dụng giao thức https://!",
"urlInvalidProtocol": "URL này chỉ có thể sử dụng giao thức http:// & https://!",
"urlInvalidHostname": "URL này có tên máy chủ bị cấm!",
"urlInvalidExtension": "URL này có phần mở rộng không hợp lệ! Chọn trong số: {0}!",
"urlInvalidPath": "URL này có đường dẫn không hợp lệ!",
"idNotUnique": "ID này không duy nhất, hãy sử dụng ID khác!",
"idNonExistent": "ID {0} không tồn tại!",
"invalidType": "Thuộc tính này cần có kiểu: {0}!",
"propertyMissing": "Thuộc tính {0} bị thiếu trong đối tượng này!",
"propertyOptional": "Thuộc tính {0} là tùy chọn trong đối tượng này!",
"objectDisabled": "Đối tượng này bị tắt, hãy bật nó bằng cách sử dụng {0}!",
"nullInvalid": "Thuộc tính này không thể là null!",
"switchInvalidType": "Điều này cần là một trong các kiểu sau: {0}!",
"objectSwitchInvalid": "Đối tượng này cần là một trong các kiểu sau: {0}!",
"invalidLanguage": "Đây là ngôn ngữ không hợp lệ!",
"invalidButton": "Nút này cần có ít nhất một {0} hoặc {1}!",
"unusedOption": "Tùy chọn {0} không được sử dụng ở bất kỳ đâu!",
"unusedQuestion": "Câu hỏi {0} không được sử dụng ở bất kỳ đâu!",
"dropdownOption": "Bảng điều khiển có bật dropdown chỉ có thể chứa các tùy chọn thuộc loại 'ticket'!"
}
},
"actions": {
"buttons": {
"create": "Truy cập Ticket",
"close": "Đóng Ticket",
"delete": "Xóa Ticket",
"reopen": "Mở lại Ticket",
"claim": "Nhận Ticket",
"unclaim": "Bỏ nhận Ticket",
"pin": "Ghim Ticket",
"unpin": "Bỏ ghim Ticket",
"clear": "Xóa Tickets",
"helpSwitchSlash": "Xem Lệnh Slash",
"helpSwitchText": "Xem Lệnh Văn Bản",
"helpPage": "Trang {0}",
"withReason": "Có Lý Do",
"withoutTranscript": "Không Có Bản Ghi"
},
"titles": {
"created": "Ticket Đã Tạo",
"close": "Ticket Đã Đóng",
"delete": "Ticket Đã Xóa",
"reopen": "Ticket Đã Mở Lại",
"claim": "Ticket Đã Nhận",
"unclaim": "Ticket Đã Bỏ Nhận",
"pin": "Ticket Đã Ghim",
"unpin": "Ticket Đã Bỏ Ghim",
"rename": "Ticket Đã Đổi Tên",
"move": "Ticket Đã Di Chuyển",
"add": "Người Dùng Đã Thêm Vào Ticket",
"remove": "Người Dùng Đã Xóa Khỏi Ticket",
"help": "Lệnh Có Sẵn",
"statsReset": "Đặt Lại Thống Kê",
"blacklistAdd": "Người Dùng Đã Bị Cấm",
"blacklistRemove": "Người Dùng Đã Được Gỡ Cấm",
"blacklistGet": "Người Dùng Bị Cấm",
"blacklistView": "Danh Sách Cấm Hiện Tại",
"blacklistAddDm": "Đã Thêm Vào Danh Sách Cấm",
"blacklistRemoveDm": "Đã Xóa Khỏi Danh Sách Cấm",
"clear": "Tickets Đã Xóa",
"roles": "Vai Trò Đã Cập Nhật",
"autoclose": "Ticket Tự Động Đóng",
"autocloseEnabled": "Tự Động Đóng Đã Bật",
"autocloseDisabled": "Tự Động Đóng Đã Tắt",
"autodelete": "Ticket Tự Động Xóa",
"autodeleteEnabled": "Tự Động Xóa Đã Bật",
"autodeleteDisabled": "Tự Động Xóa Đã Tắt"
},
"descriptions": {
"create": "Ticket của bạn đã được tạo. Nhấp vào nút bên dưới để truy cập!",
"close": "Ticket đã được đóng thành công!",
"delete": "Ticket đã được xóa thành công!",
"reopen": "Ticket đã được mở lại thành công!",
"claim": "Ticket đã được nhận thành công!",
"unclaim": "Ticket đã được bỏ nhận thành công!",
"pin": "Ticket đã được ghim thành công!",
"unpin": "Ticket đã được bỏ ghim thành công!",
"rename": "Ticket đã được đổi tên thành {0} thành công!",
"move": "Ticket đã được di chuyển đến {0} thành công!",
"add": "{0} đã được thêm vào ticket thành công!",
"remove": "{0} đã được xóa khỏi ticket thành công!",
"helpExplanation": "`<name>` => tham số bắt buộc\n`[name]` => tham số tùy chọn",
"statsReset": "Thống kê bot đã được đặt lại thành công!",
"statsError": "Không thể xem thống kê ticket!\n{0} không phải là ticket!",
"blacklistAdd": "{0} đã bị cấm thành công!",
"blacklistRemove": "{0} đã được gỡ cấm thành công!",
"blacklistGetSuccess": "{0} hiện đang bị cấm!",
"blacklistGetEmpty": "{0} hiện không bị cấm!",
"blacklistViewEmpty": "Chưa có ai bị cấm!",
"blacklistViewTip": "Sử dụng \"/blacklist add\" để cấm người dùng!",
"clearVerify": "Bạn có chắc chắn muốn xóa nhiều ticket không?\nHành động này không thể hoàn tác!",
"clearReady": "{0} tickets đã được xóa thành công!",
"rolesEmpty": "Không có vai trò nào được cập nhật!",
"autocloseLeave": "Ticket này đã được tự động đóng vì người tạo đã rời khỏi máy chủ!",
"autocloseTimeout": "Ticket này đã được tự động đóng vì không hoạt động quá `{0}h`!",
"autodeleteLeave": "Ticket này đã được tự động xóa vì người tạo đã rời khỏi máy chủ!",
"autodeleteTimeout": "Ticket này đã được tự động xóa vì không hoạt động quá `{0} ngày`!",
"autocloseEnabled": "Tự động đóng đã được bật trong ticket này!\nNó sẽ được đóng khi không hoạt động quá `{0}h`!",
"autocloseDisabled": "Tự động đóng đã được tắt trong ticket này!\nNó sẽ không tự động đóng nữa!",
"autodeleteEnabled": "Tự động xóa đã được bật trong ticket này!\nNó sẽ được xóa khi không hoạt động quá `{0} ngày`!",
"autodeleteDisabled": "Tự động xóa đã được tắt trong ticket này!\nNó sẽ không tự động xóa nữa!",
"ticketMessageLimit": "Bạn chỉ có thể tạo {0} ticket cùng lúc!",
"ticketMessageAutoclose": "Ticket này sẽ được tự động đóng khi không hoạt động trong {0}h!",
"ticketMessageAutodelete": "Ticket này sẽ được tự động xóa khi không hoạt động trong {0} ngày!",
"panelReady": "Bạn có thể tìm thấy bảng điều khiển bên dưới!\nThông báo này có thể được xóa ngay bây giờ!"
}
,
"modal": {
"closePlaceholder": "Tại sao bạn đóng ticket này?",
"deletePlaceholder": "Tại sao bạn xóa ticket này?",
"reopenPlaceholder": "Tại sao bạn mở lại ticket này?",
"claimPlaceholder": "Tại sao bạn nhận ticket này?",
"unclaimPlaceholder": "Tại sao bạn bỏ nhận ticket này?",
"pinPlaceholder": "Tại sao bạn ghim ticket này?",
"unpinPlaceholder": "Tại sao bạn bỏ ghim ticket này?"
},
"logs": {
"createLog": "Một ticket mới đã được tạo bởi {0}!",
"closeLog": "Ticket này đã được đóng bởi {0}!",
"closeDm": "Ticket của bạn đã được đóng trong máy chủ của chúng tôi!",
"deleteLog": "Ticket này đã được xóa bởi {0}!",
"deleteDm": "Ticket của bạn đã được xóa trong máy chủ của chúng tôi!",
"reopenLog": "Ticket này đã được mở lại bởi {0}!",
"reopenDm": "Ticket của bạn đã được mở lại trong máy chủ của chúng tôi!",
"claimLog": "Ticket này đã được nhận bởi {0}!",
"claimDm": "Ticket của bạn đã được nhận trong máy chủ của chúng tôi!",
"unclaimLog": "Ticket này đã được bỏ nhận bởi {0}!",
"unclaimDm": "Ticket của bạn đã được bỏ nhận trong máy chủ của chúng tôi!",
"pinLog": "Ticket này đã được ghim bởi {0}!",
"pinDm": "Ticket của bạn đã được ghim trong máy chủ của chúng tôi!",
"unpinLog": "Ticket này đã được bỏ ghim bởi {0}!",
"unpinDm": "Ticket của bạn đã được bỏ ghim trong máy chủ của chúng tôi!",
"renameLog": "Ticket này đã được đổi tên thành {0} bởi {1}!",
"renameDm": "Ticket của bạn đã được đổi tên thành {0} trong máy chủ của chúng tôi!",
"moveLog": "Ticket này đã được di chuyển đến {0} bởi {1}!",
"moveDm": "Ticket của bạn đã được di chuyển đến {0} trong máy chủ của chúng tôi!",
"addLog": "{0} đã được thêm vào ticket này bởi {1}!",
"addDm": "{0} đã được thêm vào ticket của bạn trong máy chủ của chúng tôi!",
"removeLog": "{0} đã được xóa khỏi ticket này bởi {1}!",
"removeDm": "{0} đã được xóa khỏi ticket của bạn trong máy chủ của chúng tôi!",
"blacklistAddLog": "{0} đã bị cấm bởi {1}!",
"blacklistRemoveLog": "{0} đã được gỡ khỏi danh sách cấm bởi {1}!",
"blacklistAddDm": "Bạn đã bị cấm trong máy chủ của chúng tôi!\nTừ bây giờ, bạn không thể tạo ticket!",
"blacklistRemoveDm": "Bạn đã được gỡ khỏi danh sách cấm trong máy chủ của chúng tôi!\nBây giờ bạn có thể tạo lại ticket!",
"clearLog": "{0} tickets đã được xóa bởi {1}!"
}
},
"transcripts": {
"success": {
"visit": "Truy Cập Bản Ghi",
"ready": "Bản Ghi Đã Tạo",
"textFileDescription": "Đây là bản ghi văn bản của một ticket đã xóa!",
"htmlProgress": "Vui lòng đợi trong khi bản ghi html này đang được xử lý...",
"createdChannel": "Một bản ghi {0} mới đã được tạo trong máy chủ!",
"createdCreator": "Một bản ghi {0} mới đã được tạo cho một trong các ticket của bạn!",
"createdParticipant": "Một bản ghi {0} mới đã được tạo trong một trong các ticket bạn tham gia!",
"createdActiveAdmin": "Một bản ghi {0} mới đã được tạo trong một trong các ticket bạn tham gia với tư cách quản trị viên!",
"createdEveryAdmin": "Một bản ghi {0} mới đã được tạo trong một trong các ticket bạn là quản trị viên!",
"createdOther": "Một bản ghi {0} mới đã được tạo!"
},
"errors": {
"retry": "Thử Lại",
"continue": "Xóa Không Có Bản Ghi",
"backup": "Tạo Bản Ghi Dự Phòng",
"error": "Đã xảy ra lỗi khi cố gắng tạo bản ghi.\nBạn muốn làm gì?\n\nTicket này sẽ không bị xóa cho đến khi bạn nhấp vào một trong các nút này."
}
},
"errors": {
"titles": {
"internalError": "Lỗi Nội Bộ",
"optionMissing": "Thiếu Tùy Chọn Lệnh",
"optionInvalid": "Tùy Chọn Lệnh Không Hợp Lệ",
"unknownCommand": "Lệnh Không Xác Định",
"noPermissions": "Không Có Quyền",
"unknownTicket": "Ticket Không Xác Định",
"deprecatedTicket": "Ticket Đã Lỗi Thời",
"unknownOption": "Tùy Chọn Không Xác Định",
"unknownPanel": "Bảng Điều Khiển Không Xác Định",
"notInGuild": "Không Ở Trong Máy Chủ",
"channelRename": "Không Thể Đổi Tên Kênh",
"busy": "Ticket Đang Bận"
},
"descriptions": {
"askForInfo": "Liên hệ với chủ sở hữu của bot này để biết thêm thông tin!",
"askForInfoResolve": "Liên hệ với chủ sở hữu bot này nếu vấn đề này không được giải quyết sau vài lần thử.",
"internalError": "Không thể phản hồi {0} này do lỗi nội bộ!",
"optionMissing": "Thiếu tham số bắt buộc trong lệnh này!",
"optionInvalid": "Tham số trong lệnh này không hợp lệ!",
"optionInvalidChoose": "Chọn trong số",
"unknownCommand": "Hãy thử truy cập menu trợ giúp để biết thêm thông tin!",
"noPermissions": "Bạn không được phép sử dụng {0} này!",
"noPermissionsList": "Quyền Bắt Buộc: (một trong số chúng)",
"noPermissionsCooldown": "Bạn không được phép sử dụng {0} này vì bạn đang trong thời gian chờ!",
"noPermissionsBlacklist": "Bạn không được phép sử dụng {0} này vì bạn đã bị cấm!",
"noPermissionsLimitGlobal": "Bạn không được phép tạo ticket vì máy chủ đã đạt đến giới hạn ticket tối đa!",
"noPermissionsLimitGlobalUser": "Bạn không được phép tạo ticket vì bạn đã đạt đến giới hạn ticket tối đa!",
"noPermissionsLimitOption": "Bạn không được phép tạo ticket vì máy chủ đã đạt đến giới hạn ticket tối đa cho tùy chọn này!",
"noPermissionsLimitOptionUser": "Bạn không được phép tạo ticket vì bạn đã đạt đến giới hạn ticket tối đa cho tùy chọn này!",
"unknownTicket": "Hãy thử lại lệnh này trong một ticket hợp lệ!",
"deprecatedTicket": "Kênh hiện tại không phải là ticket hợp lệ! Nó có thể là một ticket từ phiên bản Open Ticket cũ!",
"notInGuild": "{0} này không hoạt động trong DM! Vui lòng thử lại trong máy chủ!",
"channelRename": "Do giới hạn tốc độ của discord, hiện tại bot không thể đổi tên kênh. Kênh sẽ tự động được đổi tên trong 10 phút nếu bot không được khởi động lại.",
"channelRenameSource": "Nguồn gốc của lỗi này là: {0}",
"busy": "Không thể sử dụng {0} này!\nTicket hiện đang được bot xử lý.\n\nVui lòng thử lại sau vài giây!"
},
"optionInvalidReasons": {
"stringRegex": "Giá trị không khớp với mẫu!",
"stringMinLength": "Giá trị cần có ít nhất {0} ký tự!",
"stringMaxLength": "Giá trị cần có nhiều nhất {0} ký tự!",
"numberInvalid": "Số không hợp lệ!",
"numberMin": "Số cần ít nhất là {0}!",
"numberMax": "Số cần nhiều nhất là {0}!",
"numberDecimal": "Số không được phép là số thập phân!",
"numberNegative": "Số không được phép là số âm!",
"numberPositive": "Số không được phép là số dương!",
"numberZero": "Số không được phép là số không!",
"channelNotFound": "Không thể tìm thấy kênh!",
"userNotFound": "Không thể tìm thấy người dùng!",
"roleNotFound": "Không thể tìm thấy vai trò!",
"memberNotFound": "Không thể tìm thấy người dùng!",
"mentionableNotFound": "Không thể tìm thấy người dùng hoặc vai trò!",
"channelType": "Loại kênh không hợp lệ!",
"notInGuild": "Tùy chọn này yêu cầu bạn phải ở trong máy chủ!"
},
"permissions": {
"developer": "Bạn cần là nhà phát triển của bot.",
"owner": "Bạn cần là chủ sở hữu máy chủ.",
"admin": "Bạn cần là quản trị viên máy chủ.",
"moderator": "Bạn cần là người điều hành.",
"support": "Bạn cần ở trong nhóm hỗ trợ.",
"member": "Bạn cần là thành viên.",
"discord-administrator": "Bạn cần có quyền `ADMINISTRATOR`."
},
"actionInvalid": {
"close": "Ticket đã đóng!",
"reopen": "Ticket chưa đóng!",
"claim": "Ticket đã được nhận!",
"unclaim": "Ticket chưa được nhận!",
"pin": "Ticket đã được ghim!",
"unpin": "Ticket chưa được ghim!",
"add": "Người dùng này đã có thể truy cập ticket!",
"remove": "Không thể xóa người dùng này khỏi ticket!"
}
},
"params": {
"uppercase": {
"ticket": "Ticket",
"tickets": "Tickets",
"reason": "Lý Do",
"creator": "Người Tạo",
"remaining": "Thời Gian Còn Lại",
"added": "Đã Thêm",
"removed": "Đã Xóa",
"filter": "Bộ Lọc",
"claimedBy": "Được Nhận Bởi {0}",
"method": "Phương Pháp",
"type": "Loại",
"blacklisted": "Bị Cấm",
"panel": "Bảng Điều Khiển",
"command": "Lệnh",
"system": "Hệ Thống",
"true": "Đúng",
"false": "Sai",
"syntax": "Cú Pháp",
"originalName": "Tên Gốc",
"newName": "Tên Mới",
"until": "Đến",
"validOptions": "Tùy Chọn Hợp Lệ",
"validPanels": "Bảng Điều Khiển Hợp Lệ",
"autoclose": "Tự Động Đóng",
"autodelete": "Tự Động Xóa",
"startupDate": "Ngày Khởi Động",
"version": "Phiên Bản",
"name": "Tên",
"role": "Vai Trò",
"status": "Trạng Thái",
"claimed": "Đã Nhận",
"pinned": "Đã Ghim",
"creationDate": "Ngày Tạo"
},
"lowercase": {
"text": "văn bản",
"html": "html",
"command": "lệnh",
"modal": "modal",
"button": "nút",
"dropdown": "dropdown",
"method": "phương pháp"
}
},
"commands": {
"reason": "Chỉ định lý do tùy chọn sẽ hiển thị trong nhật ký.",
"help": "Nhận danh sách tất cả các lệnh có sẵn.",
"panel": "Tạo thông báo có dropdown hoặc nút (để tạo ticket).",
"panelId": "Mã định danh của bảng điều khiển bạn muốn tạo.",
"panelAutoUpdate": "Bạn có muốn bảng điều khiển này tự động cập nhật khi được chỉnh sửa không?",
"ticket": "Tạo ticket ngay lập tức.",
"ticketId": "Mã định danh của ticket bạn muốn tạo.",
"close": "Đóng ticket.",
"delete": "Xóa ticket.",
"deleteNoTranscript": "Xóa ticket này mà không tạo bản ghi.",
"reopen": "Mở lại ticket.",
"claim": "Nhận ticket.",
"claimUser": "Nhận ticket này cho người khác thay vì chính bạn.",
"unclaim": "Bỏ nhận ticket.",
"pin": "Ghim ticket.",
"unpin": "Bỏ ghim ticket.",
"move": "Di chuyển ticket.",
"moveId": "Mã định danh của tùy chọn bạn muốn di chuyển đến.",
"rename": "Đổi tên ticket.",
"renameName": "Tên mới cho ticket này.",
"add": "Thêm người dùng vào ticket.",
"addUser": "Người dùng cần thêm.",
"remove": "Xóa người dùng khỏi ticket.",
"removeUser": "Người dùng cần xóa.",
"blacklist": "Quản lý danh sách cấm ticket.",
"blacklistView": "Xem danh sách cấm hiện tại.",
"blacklistAdd": "Thêm người dùng vào danh sách cấm.",
"blacklistRemove": "Xóa người dùng khỏi danh sách cấm.",
"blacklistGet": "Nhận thông tin chi tiết từ người dùng bị cấm.",
"blacklistGetUser": "Người dùng cần nhận thông tin chi tiết.",
"stats": "Xem thống kê từ bot, thành viên hoặc ticket.",
"statsReset": "Đặt lại tất cả thống kê của bot (và bắt đầu đếm từ không).",
"statsGlobal": "Xem thống kê toàn cầu.",
"statsUser": "Xem thống kê từ người dùng trong máy chủ.",
"statsUserUser": "Người dùng cần xem.",
"statsTicket": "Xem thống kê của ticket trong máy chủ.",
"statsTicketTicket": "Ticket cần xem.",
"clear": "Xóa nhiều ticket cùng lúc.",
"clearFilter": "Bộ lọc để xóa ticket.",
"clearFilters": {
"all": "Tất Cả",
"open": "Mở",
"close": "Đã Đóng",
"claim": "Đã Nhận",
"unclaim": "Chưa Nhận",
"pin": "Đã Ghim",
"unpin": "Chưa Ghim",
"autoclose": "Tự Động Đóng"
},
"autoclose": "Quản lý tự động đóng trong ticket.",
"autocloseDisable": "Tắt tự động đóng trong ticket này.",
"autocloseEnable": "Bật tự động đóng trong ticket này.",
"autocloseEnableTime": "Số giờ ticket này cần không hoạt động để đóng.",
"autodelete": "Quản lý tự động xóa trong ticket.",
"autodeleteDisable": "Tắt tự động xóa trong ticket này.",
"autodeleteEnable": "Bật tự động xóa trong ticket này.",
"autodeleteEnableTime": "Số ngày ticket này cần không hoạt động để xóa."
},
"helpMenu": {
"help": "Nhận danh sách tất cả các lệnh có sẵn.",
"ticket": "Tạo ticket ngay lập tức.",
"close": "Đóng ticket, điều này vô hiệu hóa việc viết trong kênh này.",
"delete": "Xóa ticket, điều này tạo bản ghi khi được bật.",
"reopen": "Mở lại ticket, điều này cho phép viết lại trong kênh này.",
"pin": "Ghim ticket. Điều này sẽ di chuyển ticket lên đầu và thêm biểu tượng cảm xúc '📌' vào tên.",
"unpin": "Bỏ ghim ticket. Ticket sẽ giữ nguyên vị trí nhưng sẽ mất biểu tượng cảm xúc '📌'.",
"move": "Di chuyển ticket. Điều này sẽ thay đổi loại ticket này.",
"rename": "Đổi tên ticket. Điều này sẽ thay đổi tên kênh của ticket này.",
"claim": "Nhận ticket. Với điều này, bạn có thể cho nhóm của mình biết bạn đang xử lý ticket này.",
"unclaim": "Bỏ nhận ticket. Với điều này, bạn có thể cho nhóm của mình biết rằng ticket này lại rảnh.",
"add": "Thêm người dùng vào ticket. Điều này sẽ cho phép người dùng đọc và viết trong ticket này.",
"remove": "Xóa người dùng khỏi ticket. Điều này sẽ xóa khả năng đọc và viết của người dùng trong ticket này.",
"panel": "Tạo thông báo có dropdown hoặc nút (để tạo ticket).",
"blacklistView": "Xem danh sách cấm hiện tại.",
"blacklistAdd": "Thêm người dùng vào danh sách cấm.",
"blacklistRemove": "Xóa người dùng khỏi danh sách cấm.",
"blacklistGet": "Nhận thông tin chi tiết từ người dùng bị cấm.",
"statsGlobal": "Xem thống kê toàn cầu.",
"statsTicket": "Xem thống kê của ticket trong máy chủ.",
"statsUser": "Xem thống kê từ người dùng trong máy chủ.",
"statsReset": "Đặt lại tất cả thống kê của bot (và bắt đầu đếm từ không).",
"autocloseDisable": "Tắt tự động đóng trong ticket này.",
"autocloseEnable": "Bật tự động đóng trong ticket này.",
"autodeleteDisable": "Tắt tự động xóa trong ticket này.",
"autodeleteEnable": "Bật tự động xóa trong ticket này."
},
"stats": {
"scopes": {
"global": "Thống Kê Toàn Cầu",
"system": "Thống Kê Hệ Thống",
"user": "Thống Kê Người Dùng",
"ticket": "Thống Kê Ticket",
"participants": "Người Tham Gia"
},
"properties": {
"ticketsCreated": "Tickets Đã Tạo",
"ticketsClosed": "Tickets Đã Đóng",
"ticketsDeleted": "Tickets Đã Xóa",
"ticketsReopened": "Tickets Đã Mở Lại",
"ticketsAutoclosed": "Tickets Tự Động Đóng",
"ticketsClaimed": "Tickets Đã Nhận",
"ticketsPinned": "Tickets Đã Ghim",
"ticketsMoved": "Tickets Đã Di Chuyển",
"usersBlacklisted": "Người Dùng Bị Cấm",
"transcriptsCreated": "Bản Ghi Đã Tạo"
}
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "open-ticket",
"author": "DJdj Development",
"version": "4.0.1",
"version": "4.0.6",
"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",
@@ -25,7 +25,7 @@
"@discordjs/rest": "^2.4.2",
"@types/node": "^22.5.0",
"ansis": "^2.3.0",
"discord.js": "^14.17.2",
"discord.js": "^14.19.3",
"formatted-json-stringify": "^1.1.0",
"typescript": "^5.5.4"
},
@@ -42,7 +42,7 @@
"#opendiscord": "./dist/src/index.js",
"#opendiscord-types": "./dist/src/core/api/api.js"
},
"funding":{
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/DJj123dj"
}
+1 -1
View File
@@ -26,7 +26,7 @@ export const registerActions = async () => {
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-claimed",user.id,1,"increase")
//update category
if (params.allowCategoryChange){
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){
+1 -1
View File
@@ -28,7 +28,7 @@ export const registerActions = async () => {
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-closed",user.id,1,"increase")
//update category
if (params.allowCategoryChange){
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
const closeCategory = ticket.option.get("opendiscord:channel-category-closed").value
if (closeCategory !== ""){
try {
+1 -1
View File
@@ -20,7 +20,7 @@ export const registerActions = async () => {
const channelCategory = option.get("opendiscord:channel-category").value
const channelBackupCategory = option.get("opendiscord:channel-category-backup").value
const channelDescription = option.get("opendiscord:channel-description").value
const channelSuffix = opendiscord.options.suffix.getSuffixFromOption(option,user)
const channelSuffix = await opendiscord.options.suffix.getSuffixFromOption(option,user)
const channelName = channelPrefix+channelSuffix
//handle category
+6 -2
View File
@@ -38,7 +38,9 @@ export const registerActions = async () => {
await opendiscord.events.get("onTranscriptInit").emit([opendiscord.transcripts,ticket,channel,user])
if (instance.compiler.init){
try{
instance.initData = null
const result = await instance.compiler.init(ticket,channel,user)
instance.initData = result.initData
if (result.success && result.pendingMessage && transcriptConfig.data.general.enableChannel){
//send init message to channel
const post = opendiscord.posts.get("opendiscord:transcripts")
@@ -49,7 +51,9 @@ export const registerActions = async () => {
instance.pendingMessage = null
instance.errorReason = result.errorReason
throw new api.ODSystemError("ODAction(ot:create-transcript) => Known Init Error => "+result.errorReason)
}else instance.pendingMessage = null
}else{
instance.pendingMessage = null
}
}catch(err){
instance.success = false
cancel()
@@ -72,7 +76,7 @@ export const registerActions = async () => {
await opendiscord.events.get("onTranscriptCompile").emit([opendiscord.transcripts,ticket,channel,user])
if (instance.compiler.compile){
try{
const result = await instance.compiler.compile(ticket,channel,user)
const result = await instance.compiler.compile(ticket,channel,user,instance.initData)
if (!result.success){
instance.errorReason = result.errorReason
throw new api.ODSystemError("ODAction(ot:create-transcript) => Known Compiler Error => "+result.errorReason)
+1 -1
View File
@@ -28,7 +28,7 @@ export const registerActions = async () => {
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-reopened",user.id,1,"increase")
//update category
if (params.allowCategoryChange){
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 !== ""){
+1 -1
View File
@@ -22,7 +22,7 @@ export const registerActions = async () => {
ticket.get("opendiscord:busy").value = true
//update category
if (params.allowCategoryChange){
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 !== ""){
+2 -2
View File
@@ -604,8 +604,8 @@ const ticketEmbeds = () => {
instance.setFields(embedOptions.fields)
}
if (ticket.get("opendiscord:closed").value && ticket.get("opendiscord:autodelete-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutodelete",[ticket.option.get("opendiscord:autodelete-days").value.toString()]))
else if (!ticket.get("opendiscord:closed").value && ticket.get("opendiscord:autoclose-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutoclose",[ticket.option.get("opendiscord:autoclose-hours").value.toString()]))
if (ticket.get("opendiscord:closed").value && ticket.get("opendiscord:autodelete-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutodelete",[ticket.get("opendiscord:autodelete-days").value.toString()]))
else if (!ticket.get("opendiscord:closed").value && ticket.get("opendiscord:autoclose-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutoclose",[ticket.get("opendiscord:autoclose-hours").value.toString()]))
if (ticket.get("opendiscord:claimed").value){
const claimUser = await opendiscord.tickets.getTicketUser(ticket,"claimer")
+6 -3
View File
@@ -142,7 +142,8 @@ export const registerButtonResponders = async () => {
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build("panel-button",{guild,channel,user,option}))
}else{
//create ticket
await instance.defer("reply",true)
await instance.defer((generalConfig.data.system.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
@@ -196,7 +197,8 @@ export const registerDropdownResponders = async () => {
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build("panel-dropdown",{guild,channel,user,option}))
}else{
//create ticket
await instance.defer("reply",true)
await instance.defer((generalConfig.data.system.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
@@ -264,7 +266,8 @@ export const registerModalResponders = async () => {
})
//create ticket
await instance.defer("reply",true)
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalSource,{guild,user,answers,option})
if (!res.channel || !res.ticket){
//error
+1 -1
View File
@@ -25,7 +25,7 @@ export interface ODActionManagerIds_Default {
"opendiscord:create-transcript":{
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},
result:{compiler:ODTranscriptCompiler<any>, success:boolean, result:ODTranscriptCompilerCompileResult<any>, errorReason:string|null, pendingMessage:ODMessageBuildSentResult<true>|null, participants:{user:discord.User,role:"creator"|"participant"|"admin"}[]},
result:{compiler:ODTranscriptCompiler<any,object|null>, success:boolean, result:ODTranscriptCompilerCompileResult<any>, errorReason:string|null, pendingMessage:ODMessageBuildSentResult<true>|null, initData:object|null, participants:{user:discord.User,role:"creator"|"participant"|"admin"}[]},
workers:"opendiscord:select-compiler"|"opendiscord:init-transcript"|"opendiscord:compile-transcript"|"opendiscord:ready-transcript"|"opendiscord:logs"
},
"opendiscord:create-ticket":{
+12 -12
View File
@@ -58,9 +58,9 @@ export interface ODButtonManagerIds_Default {
"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}>,result:ODTranscriptCompilerCompileResult<{url:string}>},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<any>,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<any>,reason:string|null},workers:"opendiscord:transcript-error-continue"},
"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<any,object|null>,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<any,object|null>,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"},
}
@@ -170,7 +170,7 @@ export class ODDropdown_Default<Source extends string, Params, WorkerIds extends
* 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<any>,result:ODTranscriptCompilerCompileResult<any>},workers:"opendiscord:text-transcript"}
"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<any,object|null>,result:ODTranscriptCompilerCompileResult<any>},workers:"opendiscord:text-transcript"}
}
/**## ODFileManager_Default `default_class`
@@ -275,10 +275,10 @@ export interface ODEmbedManagerIds_Default {
"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}>,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}>,result:ODTranscriptCompilerCompileResult<{url:string}>},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}>,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<any>,reason:string|null},workers:"opendiscord:transcript-error"},
"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<any,object|null>,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: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"},
@@ -406,10 +406,10 @@ export interface ODMessageManagerIds_Default {
"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}>,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}>,result:ODTranscriptCompilerCompileResult<{url:string}>},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}>,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<any>,reason:string|null},workers:"opendiscord:transcript-error"},
"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<any,object|null>,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: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"},
+2
View File
@@ -471,6 +471,8 @@ export interface ODLanguageManagerIds_Default {
"opendiscord:norwegian":ODLanguage,
"opendiscord:russian":ODLanguage,
"opendiscord:swedish":ODLanguage,
"opendiscord:vietnamese":ODLanguage,
"opendiscord:persian":ODLanguage,
//ADD NEW LANGUAGES HERE!!!
}
+1 -1
View File
@@ -130,7 +130,7 @@ export class ODMain {
constructor(){
this.versions = new ODVersionManager_Default()
this.versions.add(ODVersion.fromString("opendiscord:version","v4.0.1"))
this.versions.add(ODVersion.fromString("opendiscord:version","v4.0.6"))
this.versions.add(ODVersion.fromString("opendiscord:api","v1.0.0"))
this.versions.add(ODVersion.fromString("opendiscord:transcripts","v2.0.0"))
this.versions.add(ODVersion.fromString("opendiscord:livestatus","v2.0.0"))
+4 -4
View File
@@ -648,8 +648,8 @@ export class ODHTTPGetRequest {
this.throwOnError = throwOnError
const newConfig = config ?? {}
newConfig.method = "GET"
if (newConfig.headers) Object.assign(newConfig.headers,{"User-Agent":"OpenDiscordBots-OpenTicket/4.0.1"})
else newConfig.headers = {"User-Agent":"OpenDiscordBots-OpenTicket/4.0.1"}
if (newConfig.headers) Object.assign(newConfig.headers,{"User-Agent":"OpenDiscordBots-OpenTicket/4.0.6"})
else newConfig.headers = {"User-Agent":"OpenDiscordBots-OpenTicket/4.0.6"}
this.config = newConfig
}
@@ -703,8 +703,8 @@ export class ODHTTPPostRequest {
this.throwOnError = throwOnError
const newConfig = config ?? {}
newConfig.method = "POST"
if (newConfig.headers) Object.assign(newConfig.headers,{"User-Agent":"OpenDiscordBots-OpenTicket/4.0.1"})
else newConfig.headers = {"User-Agent":"OpenDiscordBots-OpenTicket/4.0.1"}
if (newConfig.headers) Object.assign(newConfig.headers,{"User-Agent":"OpenDiscordBots-OpenTicket/4.0.6"})
else newConfig.headers = {"User-Agent":"OpenDiscordBots-OpenTicket/4.0.6"}
this.config = newConfig
}
+22 -17
View File
@@ -257,7 +257,7 @@ export class ODQuickButton {
/**The id of this button. */
id: ODId
/**The current data of this button */
data: ODButtonData = {
data: Partial<ODButtonData> = {
customId:"",
mode:"button",
url:null,
@@ -267,7 +267,7 @@ export class ODQuickButton {
disabled:false
}
constructor(id:ODValidId,data:ODButtonData){
constructor(id:ODValidId,data:Partial<ODButtonData>){
this.id = new ODId(id)
this.data = data
}
@@ -277,7 +277,7 @@ export class ODQuickButton {
try {
//create the discord.js button
const button = new discord.ButtonBuilder()
if (this.data.mode == "button") button.setCustomId(this.data.customId)
if (this.data.mode == "button") button.setCustomId(this.data.customId ?? "od:unknown-button")
if (this.data.mode == "url") button.setStyle(discord.ButtonStyle.Link)
else if (this.data.color == "gray") button.setStyle(discord.ButtonStyle.Secondary)
else if (this.data.color == "blue") button.setStyle(discord.ButtonStyle.Primary)
@@ -287,7 +287,7 @@ export class ODQuickButton {
if (this.data.label) button.setLabel(this.data.label)
if (this.data.emoji) button.setEmoji(this.data.emoji)
if (this.data.disabled) button.setDisabled(this.data.disabled)
if (!this.data.emoji && !this.data.label) button.setLabel(this.data.customId)
if (!this.data.emoji && !this.data.label) button.setLabel(this.data.customId ?? "od:unknown-button")
return {id:this.id,component:button}
}catch(err){
@@ -564,7 +564,7 @@ export class ODQuickDropdown {
/**The id of this dropdown. */
id: ODId
/**The current data of this dropdown */
data: ODDropdownData = {
data: Partial<ODDropdownData> = {
customId:"",
type:"string",
placeholder:null,
@@ -580,7 +580,7 @@ export class ODQuickDropdown {
mentionables:[]
}
constructor(id:ODValidId,data:ODDropdownData){
constructor(id:ODValidId,data:Partial<ODDropdownData>){
this.id = new ODId(id)
this.data = data
}
@@ -590,8 +590,9 @@ export class ODQuickDropdown {
try{
//create the discord.js dropdown
if (this.data.type == "string"){
if (!this.data.options) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 option to be present.")
const dropdown = new discord.StringSelectMenuBuilder()
dropdown.setCustomId(this.data.customId)
dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
dropdown.setOptions(...this.data.options)
if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
@@ -601,8 +602,9 @@ export class ODQuickDropdown {
return {id:this.id,component:dropdown}
}else if (this.data.type == "user"){
if (!this.data.users) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 user option to be present.")
const dropdown = new discord.UserSelectMenuBuilder()
dropdown.setCustomId(this.data.customId)
dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
if (this.data.users.length > 0) dropdown.setDefaultUsers(...this.data.users.map((u) => u.id))
if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
@@ -612,8 +614,9 @@ export class ODQuickDropdown {
return {id:this.id,component:dropdown}
}else if (this.data.type == "role"){
if (!this.data.roles) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 role option to be present.")
const dropdown = new discord.RoleSelectMenuBuilder()
dropdown.setCustomId(this.data.customId)
dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
if (this.data.roles.length > 0) dropdown.setDefaultRoles(...this.data.roles.map((r) => r.id))
if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
@@ -623,8 +626,9 @@ export class ODQuickDropdown {
return {id:this.id,component:dropdown}
}else if (this.data.type == "channel"){
if (!this.data.channels) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 channel option to be present.")
const dropdown = new discord.ChannelSelectMenuBuilder()
dropdown.setCustomId(this.data.customId)
dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
if (this.data.channels.length > 0) dropdown.setDefaultChannels(...this.data.channels.map((c) => c.id))
if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
@@ -634,6 +638,7 @@ export class ODQuickDropdown {
return {id:this.id,component:dropdown}
}else if (this.data.type == "mentionable"){
if (!this.data.mentionables) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 mentionable option to be present.")
const dropdown = new discord.MentionableSelectMenuBuilder()
const values: ({type:discord.SelectMenuDefaultValueType.User,id:string}|{type:discord.SelectMenuDefaultValueType.Role,id:string})[] = []
@@ -645,7 +650,7 @@ export class ODQuickDropdown {
}
})
dropdown.setCustomId(this.data.customId)
dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
if (this.data.mentionables.length > 0) dropdown.setDefaultValues(...values)
if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
@@ -799,14 +804,14 @@ export class ODQuickFile {
/**The id of this file. */
id: ODId
/**The current data of this file */
data: ODFileData = {
data: Partial<ODFileData> = {
file:"",
name:"file.txt",
description:null,
spoiler:false
}
constructor(id:ODValidId,data:ODFileData){
constructor(id:ODValidId,data:Partial<ODFileData>){
this.id = new ODId(id)
this.data = data
}
@@ -815,7 +820,7 @@ export class ODQuickFile {
async build(): Promise<ODFileBuildResult> {
try{
//create the discord.js attachment
const file = new discord.AttachmentBuilder(this.data.file)
const file = new discord.AttachmentBuilder(this.data.file ?? "<empty-file>")
file.setName(this.data.name ? this.data.name : "file.txt")
if (this.data.description) file.setDescription(this.data.description)
if (this.data.spoiler) file.setSpoiler(this.data.spoiler)
@@ -1055,7 +1060,7 @@ export class ODQuickEmbed {
/**The id of this embed. */
id: ODId
/**The current data of this embed */
data: ODEmbedData = {
data: Partial<ODEmbedData> = {
title:null,
color:null,
url:null,
@@ -1071,7 +1076,7 @@ export class ODQuickEmbed {
timestamp:null
}
constructor(id:ODValidId,data:ODEmbedData){
constructor(id:ODValidId,data:Partial<ODEmbedData>){
this.id = new ODId(id)
this.data = data
}
@@ -1097,7 +1102,7 @@ export class ODQuickEmbed {
if (this.data.image) embed.setImage(this.data.image)
if (this.data.thumbnail) embed.setThumbnail(this.data.thumbnail)
if (this.data.timestamp) embed.setTimestamp(this.data.timestamp)
if (this.data.fields.length > 0) embed.setFields(this.data.fields)
if (this.data.fields && this.data.fields.length > 0) embed.setFields(this.data.fields)
return {id:this.id,embed}
}catch(err){
+12 -6
View File
@@ -579,8 +579,8 @@ export class ODSlashCommandComparator {
}
}
/**Convert a `ODSlashCommandBuilder` to a universal Open Ticket slash command object for comparison. */
convertBuilder(builder:ODSlashCommandBuilder,guildId:string|null): ODSlashCommandUniversalCommand {
if (builder.type != discord.ApplicationCommandType.ChatInput) throw new ODSystemError("ODSlashCommandComparator:convertBuilder() is not supported for other types than 'ChatInput'!")
convertBuilder(builder:ODSlashCommandBuilder,guildId:string|null): ODSlashCommandUniversalCommand|null {
if (builder.type != discord.ApplicationCommandType.ChatInput) return null //throw new ODSystemError("ODSlashCommandComparator:convertBuilder() is not supported for other types than 'ChatInput'!")
const nameLoc = builder.nameLocalizations ?? {}
const descLoc = builder.descriptionLocalizations ?? {}
return {
@@ -599,8 +599,8 @@ export class ODSlashCommandComparator {
}
}
/**Convert a `discord.ApplicationCommand` to a universal Open Ticket slash command object for comparison. */
convertCommand(cmd:discord.ApplicationCommand): ODSlashCommandUniversalCommand {
if (cmd.type != discord.ApplicationCommandType.ChatInput) throw new ODSystemError("ODSlashCommandComparator:convertCommand() is not supported for other types than 'ChatInput'!")
convertCommand(cmd:discord.ApplicationCommand): ODSlashCommandUniversalCommand|null {
if (cmd.type != discord.ApplicationCommandType.ChatInput) return null //throw new ODSystemError("ODSlashCommandComparator:convertCommand() is not supported for other types than 'ChatInput'!")
const nameLoc = cmd.nameLocalizations ?? {}
const descLoc = cmd.descriptionLocalizations ?? {}
return {
@@ -812,6 +812,10 @@ export class ODSlashCommandManager extends ODManager<ODSlashCommand> {
//command is registered (and may need to be updated)
const universalBuilder = this.comparator.convertBuilder(instance.builder,instance.guildId)
const universalCmd = this.comparator.convertCommand(cmd)
//command is not of the type 'chatinput'
if (!universalBuilder || !universalCmd) return
const didChange = !this.comparator.compare(universalBuilder,universalCmd)
const requiresUpdate = didChange || (instance.requiresUpdate ? instance.requiresUpdate(universalCmd) : false)
registered.push({instance,cmd:universalCmd,requiresUpdate})
@@ -821,8 +825,10 @@ export class ODSlashCommandManager extends ODManager<ODSlashCommand> {
})
cmds.forEach((cmd) => {
//command does not exist in the manager
unused.push({instance:null,cmd:this.comparator.convertCommand(cmd),requiresUpdate:false})
//command does not exist in the manager (only append to unused when type == 'chatinput')
const universalCmd = this.comparator.convertCommand(cmd)
if (!universalCmd) return
unused.push({instance:null,cmd:universalCmd,requiresUpdate:false})
})
return {registered,unregistered,unused}
+2
View File
@@ -611,6 +611,7 @@ export class ODButtonResponderInstance {
getMessageComponent(type:"button"|"string-dropdown"|"user-dropdown"|"channel-dropdown"|"role-dropdown"|"mentionable-dropdown", id:string|RegExp): discord.ButtonComponent|discord.StringSelectMenuComponent|discord.RoleSelectMenuComponent|discord.ChannelSelectMenuComponent|discord.MentionableSelectMenuComponent|discord.UserSelectMenuComponent|null {
let result: discord.ButtonComponent|discord.StringSelectMenuComponent|discord.RoleSelectMenuComponent|discord.ChannelSelectMenuComponent|discord.MentionableSelectMenuComponent|discord.UserSelectMenuComponent|null = null
this.message.components.forEach((row) => {
if (row.type != discord.ComponentType.ActionRow) return
row.components.forEach((component) => {
if (type == "button" && component.type == discord.ComponentType.Button && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "string-dropdown" && component.type == discord.ComponentType.StringSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
@@ -898,6 +899,7 @@ export class ODDropdownResponderInstance {
getMessageComponent(type:"button"|"string-dropdown"|"user-dropdown"|"channel-dropdown"|"role-dropdown"|"mentionable-dropdown", id:string|RegExp): discord.ButtonComponent|discord.StringSelectMenuComponent|discord.RoleSelectMenuComponent|discord.ChannelSelectMenuComponent|discord.MentionableSelectMenuComponent|discord.UserSelectMenuComponent|null {
let result: discord.ButtonComponent|discord.StringSelectMenuComponent|discord.RoleSelectMenuComponent|discord.ChannelSelectMenuComponent|discord.MentionableSelectMenuComponent|discord.UserSelectMenuComponent|null = null
this.message.components.forEach((row) => {
if (row.type != discord.ComponentType.ActionRow) return
row.components.forEach((component) => {
if (type == "button" && component.type == discord.ComponentType.Button && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "string-dropdown" && component.type == discord.ComponentType.StringSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
+17 -17
View File
@@ -350,10 +350,10 @@ export class ODOptionSuffixManager extends ODManager<ODOptionSuffix> {
}
/**Instantly get the suffix from an `ODTicketOption`. */
getSuffixFromOption(option:ODTicketOption,user:discord.User): string|null {
async getSuffixFromOption(option:ODTicketOption,user:discord.User): Promise<string|null> {
const suffix = this.getAll().find((suffix) => suffix.option.id.value == option.id.value)
if (!suffix) return null
return suffix.getSuffix(user)
return await suffix.getSuffix(user)
}
}
@@ -374,7 +374,7 @@ export class ODOptionSuffix extends ODManagerData {
}
/**Get the suffix for a new ticket. */
getSuffix(user:discord.User): string {
async getSuffix(user:discord.User): Promise<string> {
throw new ODSystemError("Tried to use an unimplemented ODOptionSuffix!")
}
}
@@ -387,7 +387,7 @@ export class ODOptionSuffix extends ODManagerData {
* Use `getSuffix()` to get the new suffix!
*/
export class ODOptionUserNameSuffix extends ODOptionSuffix {
getSuffix(user:discord.User): string {
async getSuffix(user:discord.User): Promise<string> {
return user.username
}
}
@@ -400,7 +400,7 @@ export class ODOptionUserNameSuffix extends ODOptionSuffix {
* Use `getSuffix()` to get the new suffix!
*/
export class ODOptionUserIdSuffix extends ODOptionSuffix {
getSuffix(user:discord.User): string {
async getSuffix(user:discord.User): Promise<string> {
return user.id
}
}
@@ -426,11 +426,11 @@ export class ODOptionCounterDynamicSuffix extends ODOptionSuffix {
async #init(){
if (!await this.database.exists("opendiscord:option-suffix-counter",this.option.id.value)) await this.database.set("opendiscord:option-suffix-counter",this.option.id.value,0)
}
getSuffix(user:discord.User): string {
const rawCurrentValue = this.database.get("opendiscord:option-suffix-counter",this.option.id.value)
async getSuffix(user:discord.User): Promise<string> {
const rawCurrentValue = await this.database.get("opendiscord:option-suffix-counter",this.option.id.value)
const currentValue = (typeof rawCurrentValue != "number") ? 0 : rawCurrentValue
const newValue = currentValue+1
this.database.set("opendiscord:option-suffix-counter",this.option.id.value,newValue)
await this.database.set("opendiscord:option-suffix-counter",this.option.id.value,newValue)
return newValue.toString()
}
}
@@ -456,12 +456,12 @@ export class ODOptionCounterFixedSuffix extends ODOptionSuffix {
async #init(){
if (!await this.database.exists("opendiscord:option-suffix-counter",this.option.id.value)) await this.database.set("opendiscord:option-suffix-counter",this.option.id.value,0)
}
getSuffix(user:discord.User): string {
const rawCurrentValue = this.database.get("opendiscord:option-suffix-counter",this.option.id.value)
async getSuffix(user:discord.User): Promise<string> {
const rawCurrentValue = await this.database.get("opendiscord:option-suffix-counter",this.option.id.value)
const currentValue = (typeof rawCurrentValue != "number") ? 0 : rawCurrentValue
const newValue = (currentValue >= 9999) ? 0 : currentValue+1
this.database.set("opendiscord:option-suffix-counter",this.option.id.value,newValue)
await this.database.set("opendiscord:option-suffix-counter",this.option.id.value,newValue)
if (newValue.toString().length == 1) return "000"+newValue.toString()
else if (newValue.toString().length == 2) return "00"+newValue.toString()
else if (newValue.toString().length == 3) return "0"+newValue.toString()
@@ -501,13 +501,13 @@ export class ODOptionRandomNumberSuffix extends ODOptionSuffix {
if (history.includes(number)) return this.#generateUniqueValue(history)
else return number
}
getSuffix(user:discord.User): string {
const rawCurrentValues = this.database.get("opendiscord:option-suffix-history",this.option.id.value)
async getSuffix(user:discord.User): Promise<string> {
const rawCurrentValues = await this.database.get("opendiscord:option-suffix-history",this.option.id.value)
const currentValues = ((Array.isArray(rawCurrentValues)) ? rawCurrentValues : []) as string[]
const newValue = this.#generateUniqueValue(currentValues)
currentValues.push(newValue)
if (currentValues.length > 50) currentValues.shift()
this.database.set("opendiscord:option-suffix-history",this.option.id.value,currentValues)
await this.database.set("opendiscord:option-suffix-history",this.option.id.value,currentValues)
return newValue
}
}
@@ -539,13 +539,13 @@ export class ODOptionRandomHexSuffix extends ODOptionSuffix {
if (history.includes(hex)) return this.#generateUniqueValue(history)
else return hex
}
getSuffix(user:discord.User): string {
const rawCurrentValues = this.database.get("opendiscord:option-suffix-history",this.option.id.value)
async getSuffix(user:discord.User): Promise<string> {
const rawCurrentValues = await this.database.get("opendiscord:option-suffix-history",this.option.id.value)
const currentValues = ((Array.isArray(rawCurrentValues)) ? rawCurrentValues : []) as string[]
const newValue = this.#generateUniqueValue(currentValues)
currentValues.push(newValue)
if (currentValues.length > 50) currentValues.shift()
this.database.set("opendiscord:option-suffix-history",this.option.id.value,currentValues)
await this.database.set("opendiscord:option-suffix-history",this.option.id.value,currentValues)
return newValue
}
}
+44 -46
View File
@@ -15,7 +15,7 @@ import * as discord from "discord.js"
*
* The 2 default built-in transcript generators are: `opendiscord:html-compiler` & `opendiscord:text-compiler`.
*/
export class ODTranscriptManager extends ODManager<ODTranscriptCompiler<any>> {
export class ODTranscriptManager extends ODManager<ODTranscriptCompiler<any,null|object>> {
/**The manager responsible for collecting all messages in a channel. */
collector: ODTranscriptCollector
/**Alias for the client manager. */
@@ -31,12 +31,12 @@ export class ODTranscriptManager extends ODManager<ODTranscriptCompiler<any>> {
/**## ODTranscriptCompilerInitFunction `type`
* This function will initiate/prepare the transcript system for an incoming transcript.
*/
export type ODTranscriptCompilerInitFunction = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => (ODTranscriptCompilerInitResult)|Promise<ODTranscriptCompilerInitResult>
export type ODTranscriptCompilerInitFunction<InitData extends object|null> = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => (ODTranscriptCompilerInitResult<InitData>)|Promise<ODTranscriptCompilerInitResult<InitData>>
/**## ODTranscriptCompilerCompileFunction `type`
* This function will generate/compile the transcript itself.
*/
export type ODTranscriptCompilerCompileFunction<Data extends object> = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => ODTranscriptCompilerCompileResult<Data>|Promise<ODTranscriptCompilerCompileResult<Data>>
export type ODTranscriptCompilerCompileFunction<Data extends object,InitData extends object|null> = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User, initData:InitData) => ODTranscriptCompilerCompileResult<Data>|Promise<ODTranscriptCompilerCompileResult<Data>>
/**## ODTicketClearFilter `type`
* This function will finish, clear-up & shut-down the transcript system. This will also initiate the sending of the messages to all recipients.
@@ -46,13 +46,15 @@ export type ODTranscriptCompilerReadyFunction<Data extends object> = (result:ODT
/**## ODTranscriptCompilerInitResult `interface`
* This is the result which is returned by the `init()` function.
*/
export interface ODTranscriptCompilerInitResult {
export interface ODTranscriptCompilerInitResult<InitData extends object|null> {
/**Was the initialization successfull? */
success:boolean,
/**When not successfull, what was the reason? This will also be shown to the user. */
errorReason:string|null,
/**An optional message which will be sent while the transcript is being generated. */
pendingMessage:ODMessageBuildResult|null
pendingMessage:ODMessageBuildResult|null,
/**An optional object containing data from the init() function which can be used in the compiler. */
initData:InitData,
}
/**## ODTranscriptCompilerCompileResult `interface`
@@ -98,15 +100,15 @@ export interface ODTranscriptCompilerReadyResult {
*
* These functions should be defined when creating this compiler. Existing compilers already exist for html & text transcripts.
*/
export class ODTranscriptCompiler<Data extends object> extends ODManagerData {
export class ODTranscriptCompiler<Data extends object,InitData extends (object|null)> extends ODManagerData {
/*Initialise the system every time a transcript is created. Returns optional "pending" message to display while the transcript is being compiled. */
init: ODTranscriptCompilerInitFunction|null
init: ODTranscriptCompilerInitFunction<InitData>|null
/*Compile or create the transcript. Returns data to give to the ready() function for message creation. */
compile: ODTranscriptCompilerCompileFunction<Data>|null
compile: ODTranscriptCompilerCompileFunction<Data,InitData>|null
/*Unload the system & create the final transcript message that will be sent. */
ready: ODTranscriptCompilerReadyFunction<Data>|null
constructor(id:ODValidId, init?:ODTranscriptCompilerInitFunction, compile?:ODTranscriptCompilerCompileFunction<Data>, ready?:ODTranscriptCompilerReadyFunction<Data>|null){
constructor(id:ODValidId, init?:ODTranscriptCompilerInitFunction<InitData>, compile?:ODTranscriptCompilerCompileFunction<Data,InitData>, ready?:ODTranscriptCompilerReadyFunction<Data>|null){
super(id)
this.init = init ?? null
this.compile = compile ?? null
@@ -119,8 +121,8 @@ export class ODTranscriptCompiler<Data extends object> extends ODManagerData {
* It's used to generate typescript declarations for this class.
*/
export interface ODTranscriptCompilerIds {
"opendiscord:html-compiler":ODTranscriptCompiler<{url:string}>,
"opendiscord:text-compiler":ODTranscriptCompiler<{contents:string}>,
"opendiscord:html-compiler":ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,
"opendiscord:text-compiler":ODTranscriptCompiler<{contents:string},null>,
}
/**## ODTranscriptManager_Default `default_class`
@@ -131,16 +133,16 @@ export interface ODTranscriptCompilerIds {
*/
export class ODTranscriptManager_Default extends ODTranscriptManager {
get<QuestionId extends keyof ODTranscriptCompilerIds>(id:QuestionId): ODTranscriptCompilerIds[QuestionId]
get(id:ODValidId): ODTranscriptCompiler<any>|null
get(id:ODValidId): ODTranscriptCompiler<any,null|object>|null
get(id:ODValidId): ODTranscriptCompiler<any>|null {
get(id:ODValidId): ODTranscriptCompiler<any,null|object>|null {
return super.get(id)
}
remove<QuestionId extends keyof ODTranscriptCompilerIds>(id:QuestionId): ODTranscriptCompilerIds[QuestionId]
remove(id:ODValidId): ODTranscriptCompiler<any>|null
remove(id:ODValidId): ODTranscriptCompiler<any,null|object>|null
remove(id:ODValidId): ODTranscriptCompiler<any>|null {
remove(id:ODValidId): ODTranscriptCompiler<any,null|object>|null {
return super.remove(id)
}
@@ -257,6 +259,7 @@ export class ODTranscriptCollector {
const rows: ODTranscriptComponentRowData[] = []
msg.components.forEach((row) => {
const components: ODTranscriptComponentRowData["components"] = []
if (row.type != discord.ComponentType.ActionRow) return
row.components.forEach((component) => {
if (component.type == discord.ComponentType.Button){
components.push({
@@ -697,7 +700,7 @@ export interface ODTranscriptReactionData extends ODTranscriptEmojiData {
* The structure of the data sent to the Open Ticket HTML Transcripts v2 API.
*/
export interface ODTranscriptHtmlV2Data {
version:"2",
version:"2.1",
otversion:string,
language:string,
style:{
@@ -733,25 +736,33 @@ export interface ODTranscriptHtmlV2Data {
ticket:{
name:string,
id:string,
guildname:string,
guildid:string,
guildinvite:string|false,
creatorname:string,
creatorid:string,
createdname:string|false,
createdid:string|false,
closedname:string|false,
closedid:string|false,
claimedname:string|false,
claimedid:string|false,
pinnedname:string|false,
pinnedid:string|false,
deletedname:string|false,
deletedid:string|false,
closedbyname:string,
closedbyid:string,
createdpfp:string|false,
closedpfp:string|false,
claimedpfp:string|false,
pinnedpfp:string|false,
deletedpfp:string|false,
claimedname:string,
claimedid:string,
creatorpfp:string,
closedbypfp:string,
claimedpfp:string,
closedtime:number,
openedtime:number,
createdtime:number|false,
closedtime:number|false,
claimedtime:number|false,
pinnedtime:number|false,
deletedtime:number|false,
components:{
messages:number,
@@ -915,22 +926,9 @@ export interface ODTranscriptHtmlV2Data {
*/
export interface ODTranscriptHtmlV2Response {
status:"success"|"error",
id:string,
type:"transcript",
url:string,
availableUntil:number, //UNIMPLEMENTED
time:number,
estimated:{
lastdump: number,
processtime:number,
waittime:number
},
transcriptstatus:{
value:2,
data:{
fetchedmsgs:true,
uploaded:true,
inqueue:true,
processed:false,
waiting:false,
available:false
}
}
id:string
}
+16 -1
View File
@@ -13,5 +13,20 @@ export const migrations = [
for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){
globalDatabase.set("opendiscord:panel-message",panel.key,panel.value)
}
})
}),
//MIGRATE TO v4.0.2
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.2"),async () => {},async () => {}),
//MIGRATE TO v4.0.3
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.3"),async () => {},async () => {}),
//MIGRATE TO v4.0.4
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.4"),async () => {},async () => {}),
//MIGRATE TO v4.0.5
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.5"),async () => {},async () => {}),
//MIGRATE TO v4.0.6
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.6"),async () => {},async () => {})
]
+4 -4
View File
@@ -301,7 +301,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
//TICKET
{name:"ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("opendiscord:ticket",{children:[
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:ticket-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-name",{minLength:2,maxLength:50})},
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-name",{minLength:2,maxLength:45})},
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-description",{maxLength:256})},
//TICKET BUTTON
@@ -385,7 +385,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
//WEBSITE
{name:"website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("opendiscord:options-website",{children:[
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:website-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:website-name",{minLength:2,maxLength:50})},
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:website-name",{minLength:2,maxLength:45})},
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:website-description",{maxLength:256})},
//WEBSITE BUTTON
@@ -410,7 +410,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
//REACTION ROLES
{name:"role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("opendiscord:options-role",{children:[
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:role-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-name",{minLength:2,maxLength:50})},
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-name",{minLength:2,maxLength:45})},
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-description",{maxLength:256})},
//ROLE BUTTON
@@ -441,7 +441,7 @@ export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendisco
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:panel-id","openticket","panel-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-name",{minLength:3,maxLength:50})},
{key:"dropdown",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-dropdown",{})},
{key:"options",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,maxLength:25})},
{key:"options",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,minLength:1,maxLength:25})},
//EMBED & TEXT
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-text",{maxLength:4096})},
+2
View File
@@ -29,6 +29,8 @@ export const loadAllLanguages = async () => {
opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:norwegian","norwegian.json"))
opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:russian","russian.json"))
opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:swedish","swedish.json"))
opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:vietnamese","vietnamese.json"))
opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:persian","persian.json"))
/** How to add more languages?
* - Register the language to the manager (see above)
+142 -62
View File
@@ -5,7 +5,8 @@ const collector = opendiscord.transcripts.collector
const messages = opendiscord.builders.messages
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
const textConfig = transcriptConfig.data.textTranscriptStyle
const htmlVersion = Buffer.from("b3BlbnRpY2tldFRSQU5TQ1JJUFQxMjM0","base64").toString("utf8")
const htmlVersion = Buffer.from("eW91LXNob3VsZG50LWJlLWxvb2tpbmctYXQtdGhpcy0tLWZvci1tb3JlLWluZm8tY29tbWEtc2VuZC1hLW1lc3NhZ2UtdG8tZGpqMTIzZGo=","base64").toString("utf8")
const htmlDomain = atob("dC5kai1kai5iZQ==")
export const replaceHtmlTranscriptMentions = async (text:string) => {
const mainServer = opendiscord.client.mainServer
@@ -34,17 +35,30 @@ export const replaceHtmlTranscriptMentions = async (text:string) => {
return defaultroletext
}
/**
* This function is used to authenticate with the HTML Transcript API.
* It is NOT the token of the bot but an internal AUTH TOKEN from the API.
*
* Questions? Visit our discord server: https://discord.dj-dj.be
*/
function transcriptAuth(_A:{salt:number,secret:string}){
const _B = Buffer.from(_A.secret,"hex");const _C = Math["floor"](new Date().getTime()/(30*1000)).toString();const _D = Buffer.from(_C);const _E = Buffer.alloc(_D["length"]);_D.forEach((v,i) => {_E[i] = v ^ _B[i % _B["length"]];});return btoa(JSON.stringify({salt:_A.salt,secret:_A.secret,token:_E.toString("hex")}))
}
export const loadAllTranscriptCompilers = async () => {
class ODHTTPHtmlPostRequest extends api.ODHTTPPostRequest {
constructor(domain:string, htmlFinal:api.ODTranscriptHtmlV2Data){
super("https://"+domain+"/transcripts/upload?auth="+htmlVersion+"&version=2",true,{
body:JSON.stringify(htmlFinal)
constructor(transcriptAuth:string,htmlFinal:api.ODTranscriptHtmlV2Data){
super("https://"+htmlDomain+"/api/v2/upload?auth="+htmlVersion+"&token="+transcriptAuth,true,{
body:JSON.stringify(htmlFinal),
headers:{
"Content-Type":"application/json"
}
})
}
}
//TEXT COMPILER
opendiscord.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("opendiscord:text-compiler",undefined,async (ticket,channel,user) => {
opendiscord.transcripts.add(new api.ODTranscriptCompiler<{contents:string},null>("opendiscord:text-compiler",undefined,async (ticket,channel,user) => {
//COMPILE
const rawMessages = await collector.collectAllMessages(ticket)
if (!rawMessages) return {ticket,channel,user,success:false,errorReason:"Unable to collect messages! Channel not found!",messages:null,data:null}
@@ -173,27 +187,51 @@ export const loadAllTranscriptCompilers = async () => {
}))
//HTML COMPILER
opendiscord.transcripts.add(new api.ODTranscriptCompiler<{url:string}>("opendiscord:html-compiler",async (ticket,channel,user) => {
opendiscord.transcripts.add(new api.ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}|null>("opendiscord:html-compiler",async (ticket,channel,user) => {
//INIT
const req = new api.ODHTTPGetRequest("https://apis.dj-dj.be/transcripts/status.json",false)
const req = new api.ODHTTPGetRequest(atob("aHR0cHM6Ly90LmRqLWRqLmJlL2FwaS92Mi9pbml0"),false)
const res = await req.run()
if (!res || res.status != 200 || !res.body){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON error! (check otdebug.txt for details)"))
return {success:false,errorReason:"HTML Transcripts are currently unavailable!",pendingMessage:null}
//PENDING MESSAGE (not required anymore) => await messages.getSafe("opendiscord:transcript-html-progress").build("channel",{guild:channel.guild,channel,user,ticket,compiler:opendiscord.transcripts.get("opendiscord:html-compiler"),remaining:16000})
if (res.status == 200 && res.body){
const data: {salt:number,secret:string} = JSON.parse(atob(res.body))
return {success:true,errorReason:null,pendingMessage:null,initData:{auth:transcriptAuth(data)}}
}
try{
const data = JSON.parse(res.body)
if (!data || data["v2"] != "online") return {success:false,errorReason:"HTML Transcripts are currently unavailable due to maintenance!",pendingMessage:null}
}catch{
opendiscord.debugfile.writeNote("HTML Transcripts Error => unable to parse status! body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_STATUS_PARSE error! (check otdebug.txt for details)"))
return {success:false,errorReason:"HTML Transcripts are currently unavailable due to JSON parse error!",pendingMessage:null}
else{
if (res.status == 503){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_503 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"The HTML Transcripts are currently unreachable. Please try again later.",pendingMessage:null,initData:null}
}else if (res.status == 429){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_429 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"The HTML Transcripts are currently unreachable because the bot is ratelimited. Please try again in a few minutes.",pendingMessage:null,initData:null}
}else if (res.status == 403){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_403 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"The HTML Transcripts are unreachable because the bot has been banned from using the API. If you don't know why, please contact us at https://discord.dj-dj.be",pendingMessage:null,initData:null}
}else if (res.status == 500){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_500 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"Something went wrong while compiling the HTML Transcripts, please report this error at https://discord.dj-dj.be",pendingMessage:null,initData:null}
}else if (res.status == 413){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_413 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"Unable to upload transcript, file size is too large (Max 5MB)!",pendingMessage:null,initData:null}
}else{
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_UNKNOWN error! (check otdebug.txt for details)"))
return {success:false,errorReason:"Something went wrong while compiling the HTML Transcripts, please report this error at https://discord.dj-dj.be",pendingMessage:null,initData:null}
}
}
return {success:true,errorReason:null,pendingMessage:await messages.getSafe("opendiscord:transcript-html-progress").build("channel",{guild:channel.guild,channel,user,ticket,compiler:opendiscord.transcripts.get("opendiscord:html-compiler"),remaining:16000})}
},async (ticket,channel,user) => {
},async (ticket,channel,user,initData) => {
//COMPILE
if (!initData) return {ticket,channel,user,success:false,errorReason:"Could not authenticate with HTML Transcript API.",messages:null,data:null}
const rawMessages = await collector.collectAllMessages(ticket)
if (!rawMessages) return {ticket,channel,user,success:false,errorReason:"Unable to collect messages! Channel not found!",messages:null,data:null}
const messages = await collector.convertMessagesToTranscriptData(rawMessages)
@@ -350,18 +388,14 @@ export const loadAllTranscriptCompilers = async () => {
const dsf = transcriptConfig.data.htmlTranscriptStyle.favicon
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
const claimer = await opendiscord.tickets.getTicketUser(ticket,"claimer")
const closer = await opendiscord.tickets.getTicketUser(ticket,"closer")
const claimer = await opendiscord.tickets.getTicketUser(ticket,"claimer")
const pinner = await opendiscord.tickets.getTicketUser(ticket,"pinner")
const htmlFinal: api.ODTranscriptHtmlV2Data = {
version:"2",
version:"2.1",
otversion:opendiscord.versions.get("opendiscord:version").toString(true),
bot:{
name:opendiscord.client.client.user.displayName,
id:opendiscord.client.client.user.id,
pfp:opendiscord.client.client.user.displayAvatarURL({extension:"png"}),
},
language:opendiscord.languages.getLanguageMetadata()?.language ?? "english",
language:opendiscord.languages.getLanguageMetadata()?.language.toLowerCase() ?? "english",
style:{
background:{
backgroundData:(dsb.backgroundImage == "") ? dsb.backgroundColor : dsb.backgroundImage,
@@ -387,30 +421,44 @@ export const loadAllTranscriptCompilers = async () => {
enableCustomFavicon:dsf.enableCustomFavicon
}
},
bot:{
name:opendiscord.client.client.user.displayName,
id:opendiscord.client.client.user.id,
pfp:opendiscord.client.client.user.displayAvatarURL({extension:"png"}),
},
ticket:{
name:channel.name,
id:channel.id,
guildname:channel.guild.name,
guildid:channel.guild.id,
guildinvite:"",
guildinvite:false,
creatorname:(creator ? creator.displayName : "<unknown>"),
creatorid:(creator ? creator.id : "<unknown>"),
creatorpfp:(creator ? creator.displayAvatarURL() : "https://transcripts.dj-dj.be/favicon.png"),
createdname:(creator ? creator.displayName : false),
createdid:(creator ? creator.id : false),
createdpfp:(creator ? creator.displayAvatarURL() : false),
//closer is ticket deleter (small bug)
closedbyname:user.displayName,
closedbyid:user.id,
closedbypfp:user.displayAvatarURL(),
closedname:(closer ? closer.displayName : false),
closedid:(closer ? closer.id : false),
closedpfp:(closer ? closer.displayAvatarURL() : false),
//claiming is currently unused
claimedname:(claimer ? claimer.displayName : "<not-claimed>"),
claimedid:(claimer ? claimer.id : "<not-claimed>"),
claimedpfp:(claimer ? claimer.displayAvatarURL() : "https://transcripts.dj-dj.be/favicon.png"),
claimedname:(claimer ? claimer.displayName : false),
claimedid:(claimer ? claimer.id : false),
claimedpfp:(claimer ? claimer.displayAvatarURL() : false),
closedtime:new Date().getTime(),
openedtime:ticket.get("opendiscord:opened-on").value ?? new Date().getTime(),
pinnedname:(pinner ? pinner.displayName : false),
pinnedid:(pinner ? pinner.id : false),
pinnedpfp:(pinner ? pinner.displayAvatarURL() : false),
deletedname:user.displayName,
deletedid:user.id,
deletedpfp:user.displayAvatarURL(),
createdtime:ticket.get("opendiscord:opened-on").value ?? false,
closedtime:ticket.get("opendiscord:closed-on").value ?? false,
claimedtime:ticket.get("opendiscord:claimed-on").value ?? false,
pinnedtime:ticket.get("opendiscord:pinned-on").value ?? false,
deletedtime:new Date().getTime(),
//role colors are currently unused
roleColors:[],
@@ -440,39 +488,71 @@ export const loadAllTranscriptCompilers = async () => {
},
customFavicon:{
enabled:dsf.enableCustomFavicon,
image:(dsf.imageUrl) ? dsf.imageUrl : "https://transcripts.dj-dj.be/favicon.png"
image:(dsf.imageUrl) ? dsf.imageUrl : "https://t.dj-dj.be/favicon.png"
},
additionalFlags:[]
}
}
const req = new ODHTTPHtmlPostRequest("apis.dj-dj.be",htmlFinal)
const req = new ODHTTPHtmlPostRequest(initData.auth,htmlFinal)
const res = await req.run()
//check status
if (!res || res.status != 200 || !res.body){
//ratelimit error
if (res.status == 429) return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (Ratelimit)\nTry again in a few minutes!",messages,data:null}
//unknown status error
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (Unknown Error)",messages,data:null}
}
//check body
try{
//check status
if (res.status == 200 && res.body){
//check body
var data: api.ODTranscriptHtmlV2Response = JSON.parse(res.body)
if (!data || data["status"] != "success"){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (Server 500 Error)",messages,data:null}}
}catch{
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (JSON parse error)",messages,data:null}
}
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_JSON_STATUS error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"TFailed to read the response of the HTML Transcripts server.",messages:null,data:null}
}
const url = "https://transcripts.dj-dj.be/v2/"+data.time+"_"+data.id+".html"
return {ticket,channel,user,success:true,errorReason:null,messages,data:{url}}
return {
ticket,channel,user,
success:true,
errorReason:null,
messages,
data:{
url:data.url,
availableUntil:new Date(data.availableUntil)
}
}
}else{
if (res.status == 503){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_503 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"The HTML Transcripts are currently unreachable. Please try again later.",messages:null,data:null}
}else if (res.status == 429){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_429 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"The HTML Transcripts are currently unreachable because the bot is ratelimited. Please try again in a few minutes.",messages:null,data:null}
}else if (res.status == 403){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_403 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"The HTML Transcripts are unreachable because the bot has been banned from using the API. If you don't know why, please contact us at https://discord.dj-dj.be",messages:null,data:null}
}else if (res.status == 500){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_500 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"Something went wrong while compiling the HTML Transcripts, please report this error at https://discord.dj-dj.be",messages:null,data:null}
}else if (res.status == 413){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_413 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"Unable to upload transcript, file size is too large (Max 5MB)!",messages:null,data:null}
}else{
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_UNKNOWN error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"Something went wrong while compiling the HTML Transcripts, please report this error at https://discord.dj-dj.be",messages:null,data:null}
}
}
},async (result) => {
//READY
await utilities.timer(16000) //wait until transcript is ready
//WAIT UNTIL READY (not required anymore) => await utilities.timer(16000)
return {
channelMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}),
creatorDmMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}),
+1 -1
View File
@@ -20,7 +20,7 @@
INFORMATION:
============
Open Ticket v4.0.1 - © DJdj Development
Open Ticket v4.0.6 - © DJdj Development
support us: https://github.com/sponsors/DJj123dj
discord: https://discord.dj-dj.be